mix dala.battery_bench_ios (dala_dev v0.0.3)

Copy Markdown View Source

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.

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.