Survey of Software · the workshop
measured locally · download and run it yourself
Ruff's own README claims it is “10-100× faster than existing linters (like Flake8) and formatters (like Black)”. Measured against Black, formatting comes in at 16× on a clean x86 machine — inside that range, at the bottom of it. The ARM cells read higher, but they came from a laptop doing other work and this harness timed the tools in separate windows, so we cannot yet say whether the ratio really depends on architecture. A clean ARM run is the outstanding work.
Corrected 2026-08-29. The ARM cells came from a busy laptop, and this harness timed tools in separate windows — so a machine that got busier between them biases the ratio. The x86 cells are the reference: re-run two days later on a fresh machine they reproduced within 2.7%. The survey carries the full correction.
And a ratio is a snapshot, not the thing you are choosing.
Twelve times more code did not cost these tools twelve times more time — it cost
ruff check 4.7×, Flake8 6.4×, Biome 3.8× and
Pylint 23.5×, a shape that reproduced on two architectures. Three of
those are sublinear: fixed startup amortises and per-file work parallelises, so they
get relatively cheaper as you grow. Pylint gets worse faster than your codebase does. The
curve is what you are buying, and no published benchmark tells you which one — every vendor
figure is a snapshot at one codebase size, usually theirs.
Which five? → turns that into a choice.
This one does not run in your browser, and that is the finding underneath the finding: Ruff, Biome and dprint are compiled binaries. A tab cannot run them. So the instrument is a container you run on your own machine, with everything pinned — and the recipe is the point, not our numbers.
| comparison | x86 droplet | ARM laptop | the claim | ||||
|---|---|---|---|---|---|---|---|
| 1× | 12× | host 1× | cont 1× | host 12× | cont 12× | ||
| ruff vs black | 20.0× | 16.1× | 16.5× | 20.5× | 21.0× | 32.3× | 30-100× / 30× / 100× |
| ruff vs yapf | 352.1× | 1052.7× | 150.3× | 321.2× | 1171.7× | 1120.2× | 100× |
| ruff vs autopep8 | 219.5× | 616.6× | 94.7× | 157.6× | 515.0× | 495.2× | — |
| biome vs prettier | 9.8× | 21.9× | 14.5× | 11.7× | 27.8× | 31.4× | 25× |
| dprint vs prettier | 5.1× | 10.1× | 7.2× | 6.8× | 11.5× | 14.3× | 10-35× |
Ruff vs Black cannot be settled as written. 16.1× to 32.3×, and which end you get depends on your architecture. It clears the claimed 30× on ARM at 12 MB and never exceeds 20× on x86. A claim naming neither a workload nor a platform is not one a measurement can confirm.
Ruff vs YAPF is understated. 150× to 1172× on ARM, 352× to 1053× on x86, against a claimed 100×. Below the minimum measured anywhere, on either architecture.
Biome and dprint against Prettier are size-dependent, and the claims name no size. Each is wrong on a small codebase and roughly right on a large one, which means neither can be called true or false as written. That is the useful result: the defect is the missing workload, not the number.
tar xzf harness.tar.gz
cd 1-253-code-formatting
./run.sh # container: pins the OS, both runtimes, every formatter
./run-host.sh # same pins via uv + npm, if you have no Docker daemon
REPS=9 SCALE=12 ./run.sh # the large-corpus cell
./run-droplet.sh # rent a standard x86 box, run, collect, destroy
# the same container also carries the linter and type-checker benchmarks
docker run --rm -e REPS=9 -e SCALE=12 -v "$PWD/out:/out" \
--entrypoint python3 sos-fmt-bench:1.253 bench_lint.py
docker run --rm -e REPS=9 -e SCALE=12 -v "$PWD/out:/out" \
--entrypoint python3 sos-fmt-bench:1.253 bench_tsc.py
python3 summarize.py # the ratio table, derived from out/*.jsonSame container, same pinned tools, same corpus, eight cores on both machines. Ruff vs Black starts in the same place and goes opposite ways:
| ruff vs black | 1 MB | 12 MB | |
|---|---|---|---|
| aarch64 (ARM) | 20.5× | 32.3× | grows |
| x86_64 (AMD EPYC) | 20.0× | 16.1× | shrinks |
Fair objection — the ARM box is a WSL2 laptop, and its Black runs at 12 MB spanned 2.223 s to 3.599 s, a 62% spread across nine repetitions of identical work. The droplet's spanned 2%.
But the noise cancels, because both tools are timed on the same machine in the same run. A machine that is 20% slow is 20% slow for Ruff and for Black alike. So compute the ratio three ways — from the fastest runs, the median runs, the slowest runs. If noise drove it, they would disagree:
| ruff vs black, 12 MB | min/min | med/med | max/max |
|---|---|---|---|
| aarch64 container | 29.3× | 32.3× | 25.6× |
| x86_64 container | 16.6× | 16.1× | 15.6× |
The ranges do not overlap on any estimator — 25.6-32.3× against 15.6-16.6×. That gap is the platform, not the machine's mood. At 1 MB the two architectures are indistinguishable; the divergence needs a corpus big enough to show it.
Still open: our ARM cells come from a laptop, so this is the ARM machine we tested rather than ARM in general. DigitalOcean offers no ARM instances, so we could not fill that cell. A Graviton or Ampere run is the outstanding work — and if you have one, you can produce that cell yourself with the download below.
You probably should not, and the six cells are the argument for why. The same comparison reads 16.1× and 32.3× depending on your architecture and how much code you have. Run it on your codebase, on your hardware, and the answer is the one that applies to you — which a survey cannot give you, because it knows neither.
One thing the harness cannot include: blue. It pins black==22.1.0 and will not install beside a current Black at all. The survey says of it “nothing new; move existing users to Ruff” — the dependency resolver says the same thing, and dates it.