You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 412116a
Browse filesBrowse the repository at this point in the historyBrowse files
notes: cold run: decode 1.80 tok/s, prefill 10.4 tok/s, peak 3.54 GiB; run 1: decode 1.56 tok/s, prefill 10.0 tok/s, peak 3.33 GiB; run 2: decode 0.72 tok/s, prefill 10.7 tok/s, peak 3.40 GiB; 3301-token prompt, 200 decoded, mean of 2 reps, temperature 0.2
273
+
```
274
+
275
+
The block above is the output of one run of the 8B tier on an 8 GB phone, where the 5 GB model does
276
+
not fit in free memory (see below). The screen turned off during run 2, which decoded at less than
277
+
half the speed of run 1; the notes list every run so that an outlier like this stays visible.
278
+
279
+
| Field | Who fills it |
280
+
|---|---|
281
+
|`tier`, `runtime`| The benchmark. |
282
+
|`decode_tok_s`, `prefill_tok_s`, `peak_active_gib`| The benchmark (means of the 2 measured runs; peak is the highest of the two). |
283
+
|`engine_commit`| The benchmark: the pinned engine commit from `vendor.llama.pin`. |
284
+
|`reporter`|`--reporter`. |
285
+
|`notes`| The benchmark adds the cold run and each measured run (decode, prefill and, when the peak could be reset per run, peak), the prompt length, tokens decoded, run count and temperature; `--notes` is appended. |
286
+
|`device`, `soc`, `ram_gb`, `os`| The benchmark, from the Android framework. `device` is manufacturer and model. `soc` is the chip: known Qualcomm codes are mapped to marketing names (`SM8550` becomes Snapdragon 8 Gen 2), any other chip is shown as vendor and model code. `ram_gb` is total memory rounded up to the marketed size (a phone that reports 7.4 GiB shows 8). `os` is the Android release and API level. |
287
+
288
+
#### Following progress
289
+
290
+
The runner prints nothing until the run finishes. To follow progress, watch the engine log in a
291
+
second terminal:
292
+
293
+
```bash
294
+
adb logcat -s E0LLAMA
295
+
```
296
+
297
+
The benchmark sends three requests: the warmup, then runs 1 and 2. Each logs a `REND` line when it
298
+
starts, `PRE fill ...` when its prefill is done, and `OK gen=... tps=... prefill_ms=...` when it
299
+
finishes, so the third `OK gen=` line means the run is nearly over.
300
+
301
+
#### Getting representative numbers
302
+
303
+
The model file is memory-mapped. When it is larger than the free memory on the phone, the weights
304
+
are read back from flash again and again, and speed drops sharply (an 8 GB phone running the 5 GB
305
+
8B model reaches only a few tokens per second, and the warmup alone can take several minutes). For a
306
+
representative number, reboot, close other apps, keep the screen on for the whole run, and note in
307
+
`--notes` whether the phone was charging and how much memory was free. The notes list every run, so a
308
+
run that was disturbed (for example the screen turning off partway) shows up as an outlier instead of
309
+
being hidden in the mean.
310
+
311
+
#### Troubleshooting
312
+
313
+
| Message | Meaning and fix |
314
+
|---|---|
315
+
|`no usable device`|`adb devices` shows nothing usable. Unlock the phone, accept the USB debugging prompt, or set `ADB_SERIAL`. |
316
+
|`INSTRUMENTATION_FAILED` / `Unable to find instrumentation info`| The test APK is not installed. Run `./gradlew :app:installDebugAndroidTest`. |
317
+
|`edge0-<tier>.gguf not found under files/models`| The model is not staged, or the app's data was cleared. Stage it again (§1.4). |
318
+
|`load failed: ...`| The engine could not load the model. The text after it is the engine's reason. |
319
+
|`prefix cache reused N tokens`| The run did not pay a full prefill, so the prefill speed would be wrong. Re-run. |
320
+
|`prompt is N tokens, expected 2800..3800`| The tokenizer produced a different prompt length than the benchmark was designed for. Report it. |
321
+
|`decode stopped after N tokens, need exactly 200`| The model ended its answer early, or the engine hit a decode error (for example a full KV cache). The engine reports such an error as a normal, shorter answer, so the two look the same. Re-run; if it repeats, report it with the tier and the number of tokens. |
322
+
323
+
#### Code layout
324
+
325
+
| File | Role |
326
+
|---|---|
327
+
|`app/src/main/java/dev/edge0/runtime/app/bench/Bench.kt`| Tiers, instrumentation arguments, the fixed prompt, the measurement protocol and its results. |
328
+
|`app/src/main/java/dev/edge0/runtime/app/bench/BenchBlock.kt`| Renders the submission block and the per-run notes; holds the device-name, SoC and RAM helpers. |
329
+
|`app/src/main/java/dev/edge0/runtime/app/bench/DeviceProbe.kt`| Reads the device model, SoC, RAM and Android version from the Android framework, and resets the peak-memory counter. |
330
+
|`app/src/androidTest/java/dev/edge0/runtime/app/BenchTest.kt`| The instrumented test: reads the arguments, loads the model, runs the protocol, prints the block. |
331
+
|`app/src/test/java/dev/edge0/runtime/app/bench/`| JVM unit tests for the protocol and the block (no device needed). |
332
+
|`tools/bench/run_bench.sh`| The runner script described above. |
333
+
334
+
The protocol only depends on the app's `Runtime` interface, so it is unit-tested with a scripted
335
+
runtime. `app/build.gradle.kts` adds a `BuildConfig.ENGINE_COMMIT` field read from
0 commit comments