Every headline number in the README traces to a raw file in the
repository, a command that regenerates that file, and a command that renders the table.
This page lists them. Setup (checkpoints, ANE artifacts, LAYA_APPLE_CACHE,
HF_HUB_OFFLINE) is in benchmarks.md.
Read from the raw files, not typed from memory:
| Field | Value | Recorded in |
|---|---|---|
| SoC | Apple M4 Max, 16 CPU cores (12 performance, 4 efficiency) | platform.soc in raw.jsonl, placement-*.json, concurrency-*.json, probe.json; environment.cpu_cores in parity/*/coreml_*.json |
| Memory | 68719476736 bytes | environment.memory_bytes in parity/*/coreml_*.json |
| macOS | 26.6.2, build 25G83 | platform.macos, platform.macos_build |
| Python | 3.12.14 | platform.python |
| coremltools | 9.0 | platform.coremltools |
| MLX | 0.32.2 | environment.packages.mlx in parity/*/coreml_*.json and comparators-latency.jsonl; uv.lock for the laya-apple environment |
| NumPy | 2.1.3 | environment.packages.numpy; uv.lock |
| torch (comparators, goldens) | 2.7.0 | environment.packages.torch |
transformers / upstream laya / laya-coreml (comparators) |
5.17.0 / 0.3.5 / 0.1.1 | environment.packages |
| laya-apple | 1.0.0 | laya_apple in placement-*.json, concurrency-*.json |
All paths are under benchmarks/v1.0/. raw.jsonl records laya_apple: 0.3.0: it was
recorded before __version__ was set to 1.0.0 in the release commit. The comparator
files also record the pinned checkpoint revisions and weight hashes
(environment.models).
Report sections are in benchmarks/v1.0.md. Raw files are under
benchmarks/v1.0/ unless a path says otherwise. "Regenerate" commands are listed in full
under Re-running everything.
| README claim | Report section | Raw file(s) | Regenerate | Render | Environment |
|---|---|---|---|---|---|
| GPU + ANE gives 2.9–4.6× GPU-only throughput, 0 answer changes; closed-loop table (41.9 → 122.5 req/s, 2.92×, …) | Closed loop | placement-laya-thread.json, placement-laya-multilingual-process.json, placement-laya-typed-decisions-thread.json |
scripts/bench_concurrency.py --part a (step 2) |
scripts/v1_report.py hetero |
platform, args in each file |
| Open-loop P99 table (e.g. laya Poisson 43.1 req/s: 170.7 → 30.3 ms) | Open loop | concurrency-laya.json, concurrency-laya-multilingual.json, concurrency-laya-typed-decisions.json |
scripts/bench_v1.sh, part 3 (step 3) |
scripts/v1_report.py openloop |
platform, args |
Parity table: ordinary Core ML on CPU_AND_NE fails (12 / 85 / 19 hard), CPU_AND_GPU and PyTorch MPS results |
Correctness | parity/<model>/coreml_units-*.json, parity/<model>/torch_device-mps.json |
scripts/bench_v1.sh, part 2 (step 3) |
scripts/v1_report.py parity |
environment in each file |
| Parity table: laya-apple MLX FP16, ANE FP16; MLX FP32 ≤ 1.1e-5 | Correctness | parity/<model>/laya-apple-{gpu-float16,gpu-float32,ane-float16}.json |
laya-apple parity (step 4) |
scripts/v1_report.py parity |
not recorded in these files |
| laya ANE near-tie flip: one row, upstream margin 0.0035 | Correctness | parity/laya/laya-apple-ane-float16.json, field near_tie_flips[].ref_margin |
laya-apple parity laya --device ane (step 4) |
read the field; v1_report.py parity shows the count |
not recorded in the file |
Ordinary Core ML on CPU_AND_NE runs on the CPU at laya-typed-decisions L1024 (2201.8 ms) |
Correctness | comparators-latency.jsonl (units: cpu_ne, length: 1024) |
scripts/bench_v1.sh, part 1 (step 3) |
scripts/v1_report.py latency |
environment per record |
| Single-request forward P50 tables | Forward latency | raw.jsonl (laya-apple), comparators-latency.jsonl (PyTorch, Core ML ordinary) |
scripts/release_bench.py (step 1); scripts/bench_v1.sh, part 1 (step 3) |
scripts/v1_report.py latency |
platform / environment per record |
| Enumerated-shape export: 217 ms at L128 on laya | Forward latency | comparators-latency.jsonl |
scripts/bench_v1.sh, part 1 (step 3) |
scripts/v1_report.py latency (216.8) |
environment |
End to end adds 0.08–0.61 ms; typed-decisions L128 auto 9.91 ms forward, 10.06 ms predict |
End-to-end | raw.jsonl (device_requested: auto) |
scripts/release_bench.py (step 1) |
scripts/v1_report.py e2e |
platform |
| Auto routing: MLX 33.2 ms at L128 with 4 questions; multilingual L256 ANE 8.3 vs MLX 8.6 ms, MLX L128 6.4 ms | Auto routing | raw.jsonl |
scripts/release_bench.py (step 1) |
scripts/v1_report.py e2e, latency |
platform |
| Auto routing: typed-decisions L512 ANE 54 ms vs MLX 35 ms; laya ANE 39.4 ms at L128 with 4 questions (Phase -1, not v1.0) | — | research/phase-0-feasibility/raw/bench/latency.jsonl |
research/phase-0-feasibility/ harness |
research/phase-0-feasibility/reports/latency.md |
research/phase-0-feasibility/environment.md |
| v1.0 re-run reproduced v0.1 within ±1.8% over 50 configurations | Reproducibility | raw.jsonl, benchmarks/v0.1/raw.jsonl |
scripts/release_bench.py (step 1) |
scripts/compare_bench.py latency benchmarks/v0.1/raw.jsonl benchmarks/v1.0/raw.jsonl |
platform |
| Option order: upstream changes its decision in 35% (typed-decisions) and 22.5% (laya) of cases; MLX FP32 reproduces upstream exactly | Option order | option-order-upstream-*.json, option-order-{gpu-float32,gpu-float16,ane-float16}.json |
scripts/option_order.py run, research/option-order/upstream.py (step 5) |
scripts/option_order.py compare |
not recorded in these files |
| Cold start 3–5 minutes per model (v0.3, not v1.0) | — | benchmarks/v0.3/coldstart.json |
scripts/bench_coldstart.py |
benchmarks/v0.3.md |
in the file |
| Per-stream P99 under concurrency is above its solo value (v0.2, not v1.0) | — | benchmarks/v0.2/ |
scripts/bench_concurrency.py |
benchmarks/v0.2.md |
in the files |
laya-apple serve: 792 of 792 requests match unmodified upstream laya.serve 0.3.20 within the FP16 parity gate (1.3.0, not v1.0) |
benchmarks/serve-compat/README.md, "Results" |
benchmarks/serve-compat/*.json: passed per file and per case, 9 files, 792 cases |
scripts/upstream_serve_pinned.py, laya-apple serve --preload typed-decisions, then scripts/compare_serve_upstream.py per file (Reproduce) |
count cases[].passed over the 9 files |
"Setup" in the report; not recorded in the files |
laya-apple serve: 365 of those answered on the Neural Engine |
same | benchmarks/serve-compat/*-split.json, cases[].ours_device == "ane" (122 + 121 + 122) |
the --split runs above |
count ours_device |
same |
laya-apple serve: tested unmodified with 7 Jev clients |
integrations/jev-plugins/README.md |
integrations/jev-plugins/runs/2026-09-25.md: versions, install and run commands, decoded output per client |
by hand, per client, as in the run record | — | integrations/jev-plugins/README.md, "Tested" (Apple M4 Max); macOS not recorded |
laya-apple serve beside a local LLM (run 2, 1.3.0, not v1.0): short-decision P99 with the LLM busy 47.2 ms (auto) against 122.3 ms (--device gpu); LLM idle 43.2 and 55.9 ms |
benchmarks/serve/README.md, run 2; m4-max-r2/tables.md, "Decisions" |
benchmarks/serve/m4-max-r2/results.json: cells.<config>/<kind>.classes.short_1q.p99_ms_median; per-window raw data in m4-max-r2/raw/ |
benchmarks/serve/run.sh benchmarks/serve/<machine> (Run) |
benchmarks/serve/analyze.py benchmarks/serve/m4-max-r2 |
raw/campaign.json, platform (Apple M4 Max, macOS 26.6.2); LLM server version in llm_status_start |
Same run: LLM 42.2 tok/s alone, −4.0% beside serve auto, −5.3% beside --device gpu; the 1.31-point gap against the 1.28-point LLM-alone window spread (G1, G2) |
same, "LLM throughput" and "Criteria" | results.json: cells.llm_alone.llm_tok_s_median, llm_tok_s_drop, llm_alone_noise, results.gpu_free |
same | same | same |
| Same run: 0 hard mismatches and 0 errors over 7,728 decisions, max probability error 0.0039 (C1, E1) | same, "Decisions" and "Criteria" | results.json: results.correctness; n, hard_mismatches, errors per cell and class (4 cells × (1,572 + 360)) |
same | same | same |
Same run: about 4% of auto short decisions on the GPU by the backlog spill (130 of 3,144) |
same, "Validity" (V4) | results.json: validity.V4_auto_short_policy_path.spill_share_windows; cells.auto/*.classes.short_1q.devices.gpu (67 + 63) |
same | same | same |
Same run: multi-question P99 with the LLM busy against idle, 117.1 against 84.1 ms (auto) and 153.1 against 79.4 ms (--device gpu) |
same, "Decisions" | results.json: cells.<config>/<kind>.classes.mixed_3q.p99_ms_median |
same | same | same |
| Serve run 1 is invalid (V2 and V4 failed) | benchmarks/serve/README.md |
benchmarks/serve/m4-max/results.json: valid, validity |
— | benchmarks/serve/analyze.py benchmarks/serve/m4-max |
m4-max/raw/campaign.json |
| Adaptive ANE execution (1.5.0, not v1.0): 154 production episodes of laya and laya-typed-decisions all stayed on the fast path; GPU return 0.035–0.043 ms against 4.28–8.60 ms on the 1.4 path; throughput 1.038–1.042×; median episode P99 0.18–0.53 ms lower; 0 mismatches, routing failures, lost requests or crashes | research/coreml-adaptive-breaker/val_tables.md |
research/coreml-adaptive-breaker/val_results.json: phases.<2,3,5>.stats; raw runs in raw-val/ |
research/coreml-adaptive-breaker/scripts/run_val.sh <phase> (validation.md) |
research/coreml-adaptive-breaker/scripts/val_analyze.py |
raw-val/*.before.json / .after.json (machine), runtime in each run |
| Adaptive ANE execution recovery: in 12 of 12 slow episodes the breaker tripped within 40 ms and latency was A-like within 164–414 ms; the slow state's median short latency 12.3 ms against 10.0 ms | research/coreml-adaptive-breaker/phase1_tables.md |
phase1_results.json: stats.R and stats.worst_recovery; the slow state from the B rows of episodes (median_ms) against reference.m_a_ms; raw runs in raw/ |
research/coreml-adaptive-breaker/scripts/run_phase1.sh (phase1.md) |
research/coreml-adaptive-breaker/scripts/phase1_analyze.py |
raw/*.before.json / .after.json, runtime in each run |
| Prebuilt ANE artifacts (1.6.0, not v1.0): a clean-cache download on the build machine passed fetch, verify, parity and placement for all 10 model/bucket pairs; no independent second-machine check yet | benchmarks/prebuilt-artifacts-1.6.0.md, result table |
prebuilt-artifacts-1.6.0.json: imported.parity, imported.placement per bucket |
laya-apple artifacts fetch MODEL, then laya-apple artifacts verify MODEL, into an empty LAYA_APPLE_CACHE |
— | Apple M4 Max, macOS 26.6.2, coremltools 9.0; the 1.6.0 wheel built from 0ce1156; repository commit 9318106 |
Prebuilt ANE artifacts for macOS 27 (1.6.2, not v1.0): two clean-cache downloads on the build machine, released 1.6.1 with --revision and the 1.6.2 wheel at its pin, each passed fetch, verify, parity and placement for all 10 model/bucket pairs; no independent second-machine check yet |
benchmarks/prebuilt-artifacts-1.6.2-macos27.md, result tables |
prebuilt-artifacts-1.6.2-macos27.json: imported.parity, imported.placement and probe per bucket, run names the run |
laya-apple artifacts fetch MODEL [--revision 44a54765f89d434e9d85f401126cfee7d2059e7d], then laya-apple artifacts verify MODEL, into an empty LAYA_APPLE_CACHE |
— | Apple M4 Max, macOS 27.0 (26A428), coremltools 9.0; laya-apple 1.6.1 from PyPI and the 1.6.2 wheel built from 37f726c (PR #159 branch); repository commit 44a5476 |
Cold start of a new artifact location (1.6.0 docs, not v1.0): laya-typed-decisions, buckets 64/96/128, ane_startup="wait": 273.5 s cold (about 4.5 minutes) against 2.68 s warm; one run |
research/coreml-compile-cache/screen.md |
research/coreml-compile-cache/raw/c-fresh-copy.json: rows[].ready_s and warm_ready_s |
scripts/bench_coldstart.py laya-typed-decisions --modes wait --repeats 1 --location fresh-copy (README) |
read the fields | platform in the file; raw/screen-machine-{before,after}.txt |
| Core ML compile cache grows by 0.7–1.4 GB per bucket per new location, never evicted | same | research/coreml-compile-cache/raw/c-sizes.txt, raw/c-e5rt-cache.txt |
same | — | same |
Cold start on macOS 27.0 (1.6.1 release notes, not v1.0): laya-typed-decisions, buckets 64/96/128, ane_startup="wait": 210.152 s cold (median of 3) against about 2 s warm; an import's registered load about 66 s after a 27 s parity gate; 4.36 GB of compile cache per 3-bucket cold load |
research/coreml-compile-cache/results.md, Phases A–C |
research/coreml-compile-cache/raw-2026-10-02-macos27/a-fresh-copy.json: rows[].ready_s and warm_ready_s; b-import-{1,2,3}.log; c-sizes.txt, c-e5rt-cache.txt |
research/coreml-compile-cache/run-slot1b.sh (Phase A), run-slot2.sh (Phases B and C) |
read the fields | platform in the JSON files; raw-2026-10-02-macos27/machine-*.txt, setup.txt, setup-slot2.txt |
| MLX fast path (1.6.0, not v1.0): about 1–4% faster P50 on laya-typed-decisions, a screen only; compiled forward bitwise identical to eager, bucketed batching bitwise identical except laya-multilingual FP32 (max |Δlogit| 9.5e-7) | benchmarks/mlx-fast-path-screen/README.md |
the table in that file (copied from #128; raw per-run output not committed) | laya-apple benchmark laya-typed-decisions --device gpu --warmup 10 --iters 100, A-B-B-A; the integration tests named in that file |
— | Apple M4 Max, MLX 0.32.2, as recorded in #128 |
W8 research, not shipped: laya-typed-decisions L64 w8-pt at 0.650 of FP16 predict P50 (reproduced, 3 runs); every laya and laya-multilingual cell failed parity |
research/ane-w8/README.md, tables.md |
research/ane-w8/raw/replication-l64/replication.json: pooled_geomean, reproduced; research/ane-w8/results.json |
research/ane-w8/scripts/ (How to run, addendum-2.md) |
research/ane-w8/scripts/analyze.py, replicate_analyze.py |
in the raw files |
| Switchyard (1.1.0, not v1.0): late trains 1,407–1,408 / 1,422 GPU-only against 0 / 1,422 GPU + ANE; P99 decision latency 3,107.7–3,170.6 against 54.5–54.7 ms; P99 queue wait 3,095.9–3,158.8 against 39.6–42.8 ms; three runs | benchmarks/switchyard/README.md, "v1-m4-max" |
benchmarks/switchyard/v1-m4-max/raw/run-00{1,2,3}/result.json |
benchmarks/switchyard/run.sh benchmarks/switchyard/v1-m4-max |
scripts/switchyard_report.py benchmarks/switchyard/v1-m4-max |
result.json: machine, laya_apple, rounds[].conditions |
The figure docs/readme/serve-llm-load.svg in serve.md is drawn from the run-2 results.json
and raw/campaign.json above by scripts/generate_readme_svgs.py, which refuses a run
that is not valid under its own checks; --check fails if the committed figure differs
from the data.
Two README figures are not benchmark data:
- the Quickstart output (
highand 11.2 ms), from running the Quickstart; re-run it to see the values on your machine; - the
laya-apple serveterminal figure (docs/readme/serve-demo.svg, answerfix_codeon the ANE). It is one recorded session,docs/readme/serve-demo.json, captured byscripts/capture_serve_demo.pyand rendered byscripts/generate_readme_svgs.py; re-run the capture script to record it again.
Run on a quiet machine on AC power, with nothing else using the GPU or ANE, after the setup steps. Steps 1 and 3 stop early if free disk is below the minimum, and warn if the Core ML E5 caches are large; see Disk space and the Core ML E5 cache. From the repository root:
export LAYA_APPLE_CACHE=/path/to/cache
export HF_HUB_OFFLINE=1
# 1. laya-apple single-request latency: 50 configurations, 2 passes
uv run python scripts/release_bench.py benchmarks/v1.0/raw.jsonl
# 2. closed-loop GPU + ANE mix, per model, with its measured ANE placement
uv run python scripts/bench_concurrency.py --model laya --short 128 --long 512 \
--ane-placement thread --part a --output benchmarks/v1.0/placement-laya-thread.json
uv run python scripts/bench_concurrency.py --model laya-multilingual --short 96 --long 1024 \
--ane-placement process --part a --output benchmarks/v1.0/placement-laya-multilingual-process.json
uv run python scripts/bench_concurrency.py --model laya-typed-decisions --short 128 --long 1024 \
--ane-placement thread --part a --output benchmarks/v1.0/placement-laya-typed-decisions-thread.json
# 3. comparators (latency + parity) and the open-loop mix
LAYA_APPLE_ARTIFACTS=/path/to/research-artifacts scripts/bench_v1.sh
# 4. laya-apple parity against the shipped goldens (repeat per model)
uv run laya-apple --offline parity laya --device gpu --dtype float32 \
> benchmarks/v1.0/parity/laya/laya-apple-gpu-float32.json
uv run laya-apple --offline parity laya --device gpu --dtype float16 \
> benchmarks/v1.0/parity/laya/laya-apple-gpu-float16.json
uv run laya-apple --offline parity laya --device ane \
> benchmarks/v1.0/parity/laya/laya-apple-ane-float16.json
# 5. option order (upstream.py runs in the research venv, see research/option-order/)
uv run python scripts/option_order.py write-cases
uv run python scripts/option_order.py run --device gpu --dtype float32 \
--output benchmarks/v1.0/option-order-gpu-float32.json
uv run python scripts/option_order.py run --device gpu --dtype float16 \
--output benchmarks/v1.0/option-order-gpu-float16.json
uv run python scripts/option_order.py run --device ane --dtype float16 \
--output benchmarks/v1.0/option-order-ane-float16.json
(cd research/phase-0-feasibility && \
uv run python ../option-order/upstream.py --model laya \
--output ../../benchmarks/v1.0/option-order-upstream-laya.json && \
uv run python ../option-order/upstream.py --model laya-typed-decisions \
--output ../../benchmarks/v1.0/option-order-upstream-laya-typed-decisions.json)
# 6. render
uv run python scripts/v1_report.py all
uv run python scripts/compare_bench.py latency benchmarks/v0.1/raw.jsonl benchmarks/v1.0/raw.jsonl
uv run python scripts/compare_bench.py concurrency benchmarks/v0.2 benchmarks/v1.0
uv run python scripts/option_order.py compare \
benchmarks/v1.0/option-order-gpu-float32.json benchmarks/v1.0/option-order-upstream-laya.json
uv run python scripts/option_order.py compare \
benchmarks/v1.0/option-order-gpu-float32.json \
benchmarks/v1.0/option-order-upstream-laya-typed-decisions.jsonNotes:
bench_v1.shruns the comparators with the Phase -1 harness inresearch/phase-0-feasibility/, which has its own venv (upstreamlaya, torch,laya-coreml).LAYA_APPLE_ARTIFACTSpoints at that harness's Core ML packages.MODELSandBUDGEToverride the model list and the per-configuration time budget.laya-apple parityprints JSON on stdout and exits non-zero if the gate fails.benchmarks/v1.0/probe.json(the placement probe evidence) comes from.venv/bin/python scripts/bench_probe.py --runs 5 --out benchmarks/v1.0/probe.json.
From the timestamps and durations in the v1.0 raw files, on the tested machine:
| Step | Recorded |
|---|---|
| 2. closed loop | runs started at 11:32:53, 11:37:32 and 11:42:10 UTC: about 5 minutes per model |
| 3. comparator latency | first to last record, 11:56:19 to 12:09:38 UTC |
| 3. comparator parity | 10.1–187.1 s per file (seconds) |
| 3. open loop | runs started at 12:23:26, 12:26:18 and 12:29:10 UTC: about 3 minutes per model |
| 5. upstream option order | 39.1 s (laya), 39.3 s (laya-typed-decisions) |
Steps 1, 4 and the laya-apple option-order runs do not record their duration. Building
the ANE artifacts beforehand includes the on-device Core ML compile, 3–5 minutes per
model on a fresh artifact location (benchmarks/v0.3.md).
To measure a different Mac, use the community benchmark bundle
(uv run python scripts/hardware_report.py); see
community-benchmarks.md. Results from another machine are
a different profile and are not merged into the v1.0 tables.