Benchmarks
Two kinds of measurement, kept apart. The FastHenry comparison is operator-run, by hand, on one machine, and CI never runs FastHenry. The criterion suite and the scaling run are scripted. Everything on this page is rendered by site/build.py from docs/benchmarks.md; no number is typed into the page.
Machines
- FastHenry comparison and the criterion suite: Apple M3 Ultra, 28 cores, host under background load (~2× slowdown typical; both engines equally affected).
- Scaling run: AWS EC2, 8 vCPU (Xeon-class), 30 GB RAM, Linux. One thread: the measuring process was CPU-budgeted to a single core by its cgroup, so rayon ran one worker and *both* arms are single-threaded, like the "fasterhenry (dense, 1 thread)" column above. Treat the crossover as a per-thread figure; a many-core run moves both arms, not obviously by the same factor.
- SIMD: the partial-inductance kernels use 4-wide
f64lanes (wide::f64x4), as inneumann.rs.
Speed against FastHenry
| deck | filaments | FastHenry (multipole, 1 thread) | fasterhenry (dense, 28 threads) | fasterhenry (dense, 1 thread) |
|---|---|---|---|---|
| spiral | 48 | 31 ms | 10 ms | — |
| plane_trace | ~250 | 21 ms | 13 ms | — |
| serpentine | 1 000 | 69 ms | 73 ms | — |
| serpentine | 5 000 | 4.52 s | 2.06 s | 31.6 s |
| serpentine | 19 600 | 103.7 s | 83.4 s | 1 475 s |
| serpentine | 80 000 | did not finish (> 30 min) | not attempted (dense) | — |
Operator-run; method and caveats are in docs/benchmarks.md. The decks and the build of FastHenry are described in its Setup section.
Criterion bench suite
Not yet regenerated by CI — run .github/workflows/bench.yml (workflow_dispatch) or cargo bench -p fasterhenry --bench assembly --bench solve && python3 tools/bench_table.py locally to fill this in.
Regenerated by .github/workflows/bench.yml via tools/bench_table.py, which parses criterion’s own JSON output. Locally: cargo bench -p fasterhenry --bench assembly --bench solve && python3 tools/bench_table.py.
Scaling: dense vs pFFT + GMRES
assemble + one-frequency sweep, single thread. The dense arm stops where its model memory no longer fits; the table below is the data.| filaments | loops | dense s | dense model | dense peak | iterative s | iterative model | iterative peak | GMRES its |
|---|---|---|---|---|---|---|---|---|
| 960 | 720 | 0.84 | 24 MB | 61 MB | 1.71 | 53 MB | 55 MB | 5 |
| 2 400 | 1 800 | 4.15 | 150 MB | 227 MB | 4.69 | 129 MB | 130 MB | 5 |
| 4 760 | 3 570 | 20.9 | 589 MB | 635 MB | 8.95 | 240 MB | 223 MB | 5 |
| 9 800 | 7 350 | 156 | 2 497 MB | 2 198 MB | 19.4 | 487 MB | 416 MB | 5 |
| 29 928 | 22 446 | not attempted | 23 GB | — | 60.9 | 1 474 MB | 1 204 MB | 5 |
| 99 224 | 74 418 | not attempted | 256 GB | — | 207 | 4 803 MB | 3 831 MB | 5 |
Reproduce: cargo bench -p fasterhenry --bench scaling -- __report_only__. CI does not run this suite; it gates the headline with iterative_path_holds_its_scaling_headline in perf_smoke.rs.