#!/bin/sh # Installs and runs the iris `bench` build on this checkout's own emulator # (per this-machine-android's per-checkout-AVD rule; `emu serial` picks it) # and prints the report -- the iris half of `app/transcript-bench.sh`'s # job. No coordinates: the button is found by its accessibility label # through `ui-trace`, per AGENTS.md's "Driving the UI". # # Usage: ./run-bench.sh [--apk PATH] # Defaults to this checkout's own release APK # (android-project/app/build/outputs/apk/release/app-release.apk) if it # exists, else the # debug one -- build one first with ./build-apk.sh. set -eu cd "$(dirname "$0")" APK="" while [ $# -gt 0 ]; do case "$1" in --apk) APK="$2"; shift 2 ;; *) echo "run-bench.sh: unknown argument: $1" >&2; exit 1 ;; esac done if [ -z "$APK" ]; then if [ -f android-project/app/build/outputs/apk/release/app-release.apk ]; then APK=android-project/app/build/outputs/apk/release/app-release.apk else APK=android-project/app/build/outputs/apk/debug/app-debug.apk fi fi if [ ! -f "$APK" ]; then echo "run-bench.sh: no APK at $APK -- run ./build-apk.sh first" >&2 exit 1 fi SERIAL=$(emu serial) PKG=$(aapt2 dump badging "$APK" 2>/dev/null | sed -n "s/^package: name='\\([^']*\\)'.*/\\1/p") if [ -z "$PKG" ]; then BUILD_TOOLS=$(ls -d "$HOME"/Android/Sdk/build-tools/*/ | sort -V | tail -1) PKG=$("${BUILD_TOOLS}aapt2" dump badging "$APK" | sed -n "s/^package: name='\\([^']*\\)'.*/\\1/p") fi echo "run-bench.sh: installing $APK ($PKG) on $SERIAL" adb -s "$SERIAL" install -r "$APK" >/dev/null adb -s "$SERIAL" shell am force-stop "$PKG" adb -s "$SERIAL" logcat -c adb -s "$SERIAL" shell am start -n "$PKG/dev.iris.android.demo.MainActivity" >/dev/null ui-trace record -s "$SERIAL" -d 3000 --do "tap 'Run benchmark'" -o /tmp/run-bench-tap.txt >/dev/null # Which adapter drew, before any number is printed. The emulator is a GLES # machine -- its guest has no hardware Vulkan (docs/RUST.md, "What the # emulator gives a GPU app") -- so iris's runtime fallback lands on `Gl`, # and `Gl (... virgl ...)` is the host's real GPU while `Gl (... # SwiftShader ...)` is the CPU. Those two produce frame times an order of # magnitude apart and are otherwise indistinguishable in this report, so # the line is printed rather than left in logcat for somebody to think of. ADAPTER=$(adb -s "$SERIAL" logcat -d -s iris-android-app:I 2>/dev/null \ | sed -n 's/.*\(iris renderer: .*\)/\1/p' | tail -1) if [ -n "$ADAPTER" ]; then echo "run-bench.sh: $ADAPTER" else echo "run-bench.sh: no 'iris renderer:' line in logcat -- cannot say what drew this run" >&2 fi # Poll for the report line rather than a fixed sleep -- the run itself is # a fixed script (RUST.md's "Benchmark v2": 16 flings, a 20s streaming # phase, ~61s of typing, 10s of keyboard toggles, roughly 2.5 minutes end # to end) but device speed varies. 260s cap rather than v1's 90s -- v2 is # a longer script than v1's swipe-loop-only run. # The report's own first line, not the bare "iris bench report:" prefix: # `copy_report` logs that prefix too ("nothing to copy -- run the benchmark # first", which the app emits at startup), so polling for the prefix # returned instantly and the script printed a report that was never run. REPORT_LINE="iris bench report: iris bench report" i=0 while [ "$i" -lt 260 ]; do LINE=$(adb -s "$SERIAL" logcat -d -s iris-android-app:I 2>/dev/null | grep "$REPORT_LINE" || true) if [ -n "$LINE" ]; then break fi i=$((i + 1)) sleep 1 done if [ -z "$LINE" ]; then echo "run-bench.sh: no report after 260s -- check logcat by hand" >&2 exit 1 fi # -A 60 rather than v1's -A 6 -- v2's report has a per-phase block (four # phases, four lines each) on top of the frames/bench sections v1 had. adb -s "$SERIAL" logcat -d -s iris-android-app:I | grep -A 60 "$REPORT_LINE"