# `mix dala.battery_bench_ios`
[🔗](https://github.com/manhvu/dala_dev/blob/main/lib/mix/tasks/dala.battery_bench_ios.ex#L1)

Builds a benchmark app, deploys it to a physical iPhone/iPad, and measures
battery drain over time.

Run this from your Dala app project directory (the one containing `ios/`,
`dala.exs`, and your Elixir source). It requires `bundle_id` to be set in
`dala.exs`:

    config :dala_dev,
      dala_dir:   "/path/to/dala",
      bundle_id: "com.example.myapp"

## Prerequisites

libimobiledevice is required for battery readings:

    brew install libimobiledevice

The device must be trusted on this Mac (accept "Trust This Computer" when
connecting via USB). Xcode 15 or later is required for `xcrun devicectl`.

## Battery measurement

iOS exposes battery capacity via libimobiledevice's `ideviceinfo` tool.
If the device reports `BatteryMaxCapacity` (mAh), drain is shown in mAh like
the Android benchmark. Otherwise, it falls back to percentage points
(1% ≈ 40–60 mAh on most iPhones).

WiFi-only measurements are not possible on iOS — USB-connected readings are
skewed because the cable can trickle-charge. To minimise this, use a USB-only
data cable (no charging), or note the baseline with and without cable.

## Recommended workflow (Dala projects)

Dala projects use `ios/build_device.sh` rather than a full Xcode project,
which means the bench task's `xcodebuild` path doesn't apply. Use this
two-step pattern instead:

    # 1. Push BEAM flags via dala.deploy (no native rebuild — ~5 sec).
    mix dala.deploy --beam-flags "" --ios               # tuned (Nerves)
    mix dala.deploy --beam-flags "-S 6:6 -A 8" --ios    # untuned variant

    # 2. Run the bench with --no-build, specifying the phone's WiFi IP.
    mix dala.battery_bench_ios --no-build --wifi-ip 10.0.0.120

Find the phone's WiFi IP in Settings → Wi-Fi → (i) → IP Address.

See `README.md` for the full rationale and recovery procedure if a flag
combination crashes the BEAM (which can happen if you request more
threads than iOS allows per process).

## Usage (with built-in Xcode build path)

    mix dala.battery_bench_ios
    mix dala.battery_bench_ios --no-beam
    mix dala.battery_bench_ios --preset nerves
    mix dala.battery_bench_ios --flags "-sbwt none -S 1:1"
    mix dala.battery_bench_ios --duration 3600 --device UDID
    mix dala.battery_bench_ios --no-build   # re-run without rebuilding

## Options

  * `--duration N`      — benchmark duration in **seconds** (default: 1800 = 30 min)
  * `--device UDID`     — device UDID (auto-detected if one device connected)
  * `--wifi-ip IP`      — phone's WiFi IPv4 (recommended; bypasses auto-discovery)
  * `--no-beam`         — baseline: build without starting the BEAM at all
  * `--no-keep-alive`   — skip the silent-audio background keep-alive call
  * `--preset NAME`     — named BEAM flag preset (Xcode-build path only)
  * `--flags "..."`     — arbitrary BEAM VM flags (Xcode-build path only)
  * `--no-build`        — skip Xcode build and install; benchmark current install
  * `--scheme NAME`     — Xcode scheme name (default: camelized app name)
  * `--log-path PATH`   — override CSV log location (default: `_build/bench/run_<ts>.csv`)
  * `--no-csv`          — skip CSV logging
  * `--skip-preflight`  — bypass the preflight checks (USB/app/BEAM/RPC/NIF/keep-alive)

## What the presets do

  * `untuned`   — raw BEAM with no tuning flags (highest power use baseline)
  * `sbwt`      — only busy-wait disabled (`-sbwt none`)
  * `nerves`    — full Nerves set: single scheduler + busy-wait off + multi_time_warp
  * (default)   — same as `nerves` (production default)

## Understanding the results

iOS battery percentage resolution is coarse. A 30-minute run should produce
2–5% drain, enough to see the difference between no-BEAM and tuned-BEAM.
Run at a fixed screen brightness or with the screen locked for reproducible
results across runs.

## Under the hood

`mix dala.battery_bench_ios` orchestrates the following commands:

    # Build
    xcodebuild -workspace ios/*.xcworkspace -scheme SCHEME \
      -configuration Debug -sdk iphoneos \
      -derivedDataPath /tmp/dala_bench_ios_STAMP       [OTHER_CFLAGS='$(inherited) -DFLAG']

    # Install and launch
    xcrun devicectl device install app --device UDID /path/to/App.app
    xcrun devicectl device process launch --terminate-existing --device UDID \
      com.example.myapp                   # → captures PID

    # Lock screen
    idevicediagnostics -u UDID sleep

    # Poll battery every 10s
    ideviceinfo -u UDID -q com.apple.mobile.battery -k BatteryCurrentCapacity
    ideviceinfo -u UDID -q com.apple.mobile.battery -k BatteryMaxCapacity

    # Stop app
    xcrun devicectl device process terminate --device UDID --pid PID

BEAM tuning flags are injected as `OTHER_CFLAGS` build settings passed to
xcodebuild, matching the same C preprocessor defines used in the Android build.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
