← board

Bench: give mandelbrot and raytracer an FPC-comparable variant

The answer to that question: it is NOT dialect extensions

Worth recording, because it is the natural assumption and it is wrong. The dialect is fine — FPC accepts our sources. What blocks the comparison is unit dependencies on pxx-only libraries:

bench FPC level today why
nbody ✅ compared uses math — portable
fib ✅ compared no uses clause
sieve fixed 2026-07-14 uses sysutils only; was being skipped by a tooling bug (below)
mandelbrot uses baseunix, ansitermansiterm is a pxx RTL unit
raytracer uses image, png, hashing, platform — all pxx lib units
selfcompile separate issue: compiler.pas does not build under FPC at HEAD — the open fpc-bootstrap regression (bad=603cf2bda859), not a bench problem

Two of the three gaps were not gaps at all:

What is left

mandelbrot and raytracer need portable variants in bench/portable/ — same computation, no pxx-only units:

Keep the originals as they are — they are Track B/E demos and should stay idiomatic (they exist to use our libraries). The portable variants are bench fixtures, not replacements.

Why bother

The fpc level is our only external speed oracle. Right now it covers one float benchmark, one call-heavy int benchmark and one memory-bound int benchmark — but not the float-heavy call-dense shape the raytracer represents, which is where an optimiser's inlining and register allocation actually show up. nbody at 565ms (pxx -O2) vs 64ms (fpc) says there is a large gap to explain; more comparable workloads is how you find out where it lives.

Acceptance — MET 2026-07-15

bench/portable/raytracer.pas exists, uses only units FPC also has (math), is registered in BENCH_SUITE with fpc_ok=True, and produces fpc rows in tstate/bench.tsv alongside the -O0/-O2/-O3 ones. Both mandelbrot and raytracer done — ticket ready to resolve.

Where the gap stands now

Three FPC-comparable rows, and all three say the same thing:

workload pxx (best -O) fpc -O2 ratio
sieve (memory-bound int) 63.8ms 31.8ms 2.0x
mandelbrot-p (float compute) 1166ms 364ms 3.2x
nbody (float) 565ms 64ms 8.8x
fib (call-heavy int) 164ms 114ms 1.4x

nbody's 8.8x is the outlier and the obvious thing to explain — it is the only one using math, so part of that may be RTL rather than codegen. Track O has the material now.

Log