parfast Round Book

parfast does the same job in a fraction of the time, and the bigger the job the smaller the fraction. On an ordinary Intel desktop - a six-core i5-10600KF, 10 GiB at 15% parity - building the parity set takes par2cmdline-turbo 2.6 min and parfast 19 s. Repairing a lost file out of that set is 1.8 min against 27 s. Verifying it is 4.3 s against 1.7 s.

Smallest margin first: verify 2.5x, repair 4.0x, create 7.8x. Push that repair to the deepest this set can go and it is 5.3x. The quick jobs stay quick either way; the ones you wait for are the ones that change.

Every figure on this page is measured against the fastest rival at that job, never the slowest. par2cmdline-turbo leads at repair and verify; ParPar leads at create, by a second. That closeness is no coincidence: turbo carries a ParPar processing backend, so at create the two are largely the same engine, with ParPar holding a few optimisations turbo has not taken. Both are fair competition, and which of them you pick does not move the headline.

The slower tools are in the tables on purpose. par2cmdline needs 27 min to build the same parity set and phpar2 needs 33 min - real numbers from tools people still run, and leaving them out would be hiding something. They are simply not what a headline should be measured against, because nobody would call them fair competition.

All of these benchmarks were produced by automated harnesses, on a variety of spare machines of varying ages and specifications, running unattended and refusing to time a leg on a busy box. The harnesses and every log are published beside this page.

Everything below is the evidence for that, with its status, the exact command line behind it and the repetition-to-repetition spread behind every median. Nothing is extrapolated: each number is a CLI timing from a log, and each repair passed a SHA-256 check of every member before its time counted.

Published  ·  12 September 2026  ·  parfast 1.5.0-beta.1 vs par2cmdline-turbo 1.5.0 vs par2j 1.3.3.5

Why the gap grows with the job

parfast has two ways of doing the arithmetic, and which one runs is decided by the size of the repair.

Below roughly a thousand blocks it uses ordinary Reed-Solomon, the same arithmetic every other PAR2 tool uses, done a little faster: one to three times at those depths, from better use of the cores and less reading. Most everyday repairs, a handful of lost articles, sit in this range, and what to expect there is "quicker", not "a different class of tool".

Above it the work moves to a transform-based solver, whose cost grows far more slowly with the number of blocks than conventional Reed-Solomon does. That is why the charts on this page are curves and not one number: the harder the job, the wider the gap, from about 5x at two thousand blocks to between 3x and 15x at the format's ceiling depending on the machine, and it is why a deep repair that takes the fastest rival half an hour takes parfast minutes. The 15% ladders measure the first solver with the second barely engaged; the 100% rounds measure the second.

Creating a parity set always uses the transform. There is no small-job path on the create side: every recovery block is produced by the transform-based solver, whatever the size of the set. That is why building parity is the widest margin on this page wherever the set fits in memory: 8x on the i5's 10 GiB set at 15%, and 6x to 28x across the 10 to 80 GiB sweep on the M3 Ultra, widening as the set and the parity grow. A large set with many recovery blocks is the shape the transform is built for, and the shape that costs a conventional tool the most; the one place the margin closes is a set that does not fit the machine, where memory rather than arithmetic sets the pace, and that case is measured too, on the 31 GB laptop.

The machines and the rounds

Every machine on this page, and every round it ran.

Intel i5-10600KF (2020)
6 cores / 12 threads, 64 GB, Windows 11 desktop
Intel Core Ultra 9 386H (2026)
16 cores, 31 GB, Windows 11 laptop
Apple M3 Ultra (2025)
32 cores, 256 GB, macOS 27 desktop
Apple M5 Max (2026)
18 cores, 128 GB, macOS 27 laptop
Intel i5-10600KF (2020) - full range
6 cores / 12 threads, 64 GB - 23 members, 23 GiB, 100% redundancy, m to 32,177
Intel Core Ultra 9 386H (2026) - full range
16 cores, 31 GB laptop - 23 members, 23 GiB, 100% redundancy, m to 32,177
Apple M5 Max (2026) - full range
18 cores, 128 GB laptop - 23 members, 23 GiB, 100% redundancy, m to 32,177
Apple M3 Ultra (2025) - full range
32 cores, 256 GB - 23 members, 23 GiB, 100% redundancy, m to 32,177, turbo at -T23
Intel create sweep, with a memory-capped arm
Core Ultra 9, 31 GB: six sizes to 40 GiB, three parity levels, a third arm under -m2048. One run per cell. In the create section, with what the -m arm did and did not do.
25% and 30% redundancy
M3 Ultra, ten cells, three interleaved repetitions. The single-run inversions are gone; parfast's wall spread at 50-80 GiB is printed.
Memory floor - deep repair under a tight -m
Landed on the 31 GB laptop. -m8192 360 s, -m2048 352 s, -m512 1,372 s, all restoring 23/23.
Fast mode, per class of machine
The shipping build on the i5 (AVX2 class) and the Core Ultra 9 (GFNI class): eleven depths, three repetitions, an A/A control; nine half-step depths on three Apple parts. On by default everywhere. In the fast-mode section.
Fast mode capability
Engages on Apple silicon and on x86 with or without GFNI. See the section below for which machines have it on by default.

The four jobs, and how long each takes

Left of each arrow is the fastest rival, right is parfast, same work on the same machine. The first three are the jobs that make you wait; the fourth is the one that does not, and the gap between them is the whole argument.

Three of the four are the six-core Intel desktop; the fourth is the 16-core Intel laptop, with the Apple ratio named beside it for contrast.

2.5 min → 28 s
A full repair at the 15% parity ceiling - 2,098 blocks of a 10 GiB set on a 6-core Intel i5. Fastest rival is par2cmdline-turbo; par2j needs 3.6 min. 5.3x
2.5 min → 19 s
Building the parity set - 10 GiB at 15%, same i5, seven tools measured. Fastest rival is ParPar; the slowest, phpar2, takes 33 min. 7.8x
8.8 s → 3.7 s
Verifying 20 GiB on that i5, the check every repair pays first. Faster, but this is the small margin - and on a slow enough disk it goes to nothing. 2.4x
35 min → 10 min
The deepest repair PAR2 allows - all 32,177 blocks of a 23 GiB set, on the 16-core Intel Core Ultra 9 laptop, two repetitions agreeing within 1%. The margin peaks earlier: the 6-core i5 is 6.7x at 24,576 blocks on its first pass, and 12.5x around 8,000. Apple silicon opens it much wider - 14.7x on an M5 Max at the same ceiling. 3.4x

All seven PAR2 tools, side by side

Seven PAR2 tools on the same 10 GiB set, same Intel desktop, same command shapes. This is here first because it settles who the rival actually is: par2cmdline-turbo is the fastest of the others at every job, by a wide margin over the rest. Everything after this page compares parfast to turbo alone - not to flatter the comparison, but because beating the field means beating turbo, and a chart with seven lines on it is harder to read and says less.

evidence

Repairing a lost file

Intel i5-10600KF, 6 cores / 12 threads, 64 GB, Windows 11 - 10 GiB in 10 files, 15% parity, 13,990 source blocks - medians of 2 repetitions

One member of ten deleted: 1,399 blocks to rebuild.

0 s50 s100 s150 sparfast27 spar2cmdline-turbo1.8 min 4xrarpar2.3 min 5xpar2j (MultiPar)2.7 min 6xpar2cmdline19.4 min 44xphpar220.4 min 46xshorter is better; linear; a cut bar runs past the axis

Reading this. One depth only - 1,399 blocks, from a single deleted file. That is a common real failure, and it is also below the range where parfast's transform earns its keep, so this understates the gap against turbo: the same pair reaches 12.5x by 8,000 blocks on this machine. Medians of two repetitions; the table below carries the same six tools at 100% parity to 4,096 blocks.

evidence

Building the parity set

Intel i5-10600KF, 6 cores / 12 threads, 64 GB, Windows 11 - 10 GiB in 10 files, 15% parity, 13,990 source blocks - medians of 2 repetitions
0 s50 s100 s150 sparfast19 sParPar2.5 min 8xpar2cmdline-turbo2.6 min 8xpar2j (MultiPar)2.7 min 9xrarpar3.0 min 9xpar2cmdline27.3 min 87xphpar232.6 min 104xshorter is better; linear; a cut bar runs past the axis

Reading this. Building parity from scratch, so every tool does the same job with no damage involved. ParPar appears only here - it creates parity and does not verify or repair, which is its design and not a gap in the test. It edges turbo by about a second, and that near-tie is structural rather than luck: turbo is a par2cmdline fork that uses a ParPar processing backend, so the top two bars here are close relatives. ParPar carries a few optimisations turbo has not picked up, which is the second.

evidence

Verifying an undamaged set

Intel i5-10600KF, 6 cores / 12 threads, 64 GB, Windows 11 - 10 GiB in 10 files, 15% parity, 13,990 source blocks - medians of 2 repetitions
0 s5 s10 s15 sparfast2 spar2cmdline-turbo4 s 3xpar2cmdline8 s 5xpar2j (MultiPar)9 s 6xrarpar15 s 9xphpar251 s 30xshorter is better; linear; a cut bar runs past the axis

Reading this. An undamaged set, which is the case a verify actually meets. parfast defers the parity payloads on a clean set and the others hash them, so part of this gap is reading less rather than reading faster - at this 15% parity level that difference is small, but on a 100%-parity set it dominates. ParPar is absent because it does not verify.

What it does and does not show

One machine, one set, one kind of damage: a single member deleted, the common real failure, costing 1,399 blocks. It ranks the field; the ladders after it characterise the two tools that matter across their range. ParPar appears only in the create chart because it creates parity and does not verify or repair. Every repair leg on this page is gated on a SHA-256 of every member afterwards, never on the tool's exit code (par2j returns 16 on a successful repair).

The second phase below rebuilds the same set at 100% parity, so the six repairing tools can be taken deeper. par2cmdline and phpar2 ran once per depth: their 4,096-block legs alone took an hour each, and deeper legs would only repeat what the shallower ones say. The quick tools' deeper depths (5,500 to 13,990) have not been run yet.

evidence

Rebuilding more of the set, at 100% parity

Intel i5-10600KF, 6 cores / 12 threads, 64 GB, Windows 11 - 10 GiB in 10 files, 100% parity, 13,990 source and 13,990 recovery blocks - one repetition per cell; stopped after 4,096 by decision, deeper depths deferred
1x2x5x10x20x50x100x1,3992,0984,096blocks that have to be rebuilttimes slower than parfast (log scale)phpar2 95xpar2cmdline 81xpar2j 10xrarpar 9xturbo 7x
blocks to rebuildcountparfastsecondspar2cmdline-turbosecondspar2cmdlinesecondsphpar2secondspar2j (MultiPar)secondsrarparsecondsvs turbotimesvs par2cmdlinetimesvs phpar2timesvs par2j (MultiPar)timesvs rarpartimes
1,39928113113011661761184x40x41x6x4x
2,09832159163617952391655x51x56x7x5x
4,09644293357241774283877x81x95x10x9x

Reading this. Same machine, same ten files, the parity set rebuilt at 100% so a deeper repair is possible. Every leg restored 10 of 10 members by SHA-256. par2cmdline and phpar2 are 40 to 95 times parfast here and get slower in proportion as the job grows, which is why they ran once per depth and why the round stopped where it did.

Read this section as who is the one to beat. The ladders after it are the characterisation, and they are of parfast and turbo only, because those are the two that can be run that far.

From one lost block to losing everything

The 15% ladders below stop at 2,098 recovery blocks, which barely enters the range where the transform pays - they measure the easy end of the problem. This round runs a 23 GiB set at 100% redundancy out to 32,177 blocks, the deepest repair the format can describe, and it is where the claim is made: the gap widens with the difficulty of the job. Switch to times slower to read it directly, and note the left end - at one lost block the margin is real but modest; by the right end the same two tools are minutes against half an hour.

The "verify only" row is not a verify result

It says 20x on one machine while the verify figures everywhere else on this page say 2.1x to 2.6x. Both are measured correctly; the fixture explains the difference, and the number to quote is the small one. On a clean set parfast defers the parity payloads and turbo hashes them. At 15% parity that is 1.5 GiB out of 11.5 and barely shows; on this 100%-parity fixture the parity is as large as the payload, so deferring it halves the work (33.9 CPU-seconds against 62.8). The rest is parallelism: parfast ran that verify across 21.9 cores, turbo across 2.0, and that part holds at any parity level. So 20x is 1.9x of reading less times 10.7x of using the machine, and at a realistic parity level only the second factor remains.

100% redundancy is not a common setting in the wild, and it is used here for a specific reason: PAR2 caps a set at 32,768 slices, so with 15% parity the deepest possible repair is about 4,900 blocks whatever the file size. The only way to exercise the top of the range at all is to raise the redundancy. Getting there is also why the same ladder was run on the two Intel boxes and the M5.

evidence

Intel i5-10600KF

cores 6 / 12 threads  ·  ram 63.9 GB  ·  os Microsoft Windows 11 Pro  ·  set 23 files, 23.0 GiB  ·  blocks 32177  ·  redundancy 100.0%  ·  slice 768000  ·  reps 1 of 2 completed  ·  argv r -q -t12 -T12 f.par2  ·  binary cae5a6f368 (8b0b67ec4d)

First pass. parfast ran every depth to 32,177; par2cmdline-turbo and par2j had not run the last depth when the machine was needed for the fast-mode gate, so the comparison stops at 24,576 and the 32,177 row shows parfast alone. Further repetitions follow the seven-tool round on this machine.

parfastpar2cmdline-turbopar2j (MultiPar)

Reading this. 100% parity is not a real-world setting - it is here so the repair can reach PAR2's 32,768-block ceiling, which 15% parity can never do. The curve turns: the margin peaks around 16,384 blocks and falls back at the very end, so no single multiplier describes it. On the linear axis parfast sits close to the floor across most of the range; that is a real span of roughly 400 to 1, not a zero. And the verify row in the table is not a verify result - see the note above it.

blocks to rebuildcountparfastsecondspar2cmdline-turbosecondspar2j (MultiPar)secondsvs turbotimesvs par2j (MultiPar)times
verify only3.7734.851.99.2x13.8x
113.742.576.73.1x5.6x
415.344.785.82.9x5.6x
1619.349.31302.6x6.7x
6435.971.31692.0x4.7x
25665.794.61951.4x3.0x
1,02465.82203343.3x5.1x
2,04870.63905355.5x7.6x
4,09689.17359558.3x10.7x
8,1921151442190912.5x16.6x
16,3842452964420812.1x17.2x
24,576660444671406.7x10.8x
32,1771135----
evidence

Intel Core Ultra 9 386H

cores 16  ·  ram 31.4 GB  ·  os Microsoft Windows 11 Home  ·  set 23 files, 23.0 GiB  ·  blocks 32177  ·  redundancy 100.0%  ·  slice 768000  ·  reps 2  ·  argv r -q -t16 -T16 f.par2  ·  binary cae5a6f368 (8b0b67ec4d)

Sole round on that box for its whole window. Two earlier attempts overlapped another round on the same machine and are void, kept on disk and not shown.

parfastpar2cmdline-turbopar2j (MultiPar)
blocks to rebuildcountparfastsecondspar2cmdline-turbosecondspar2j (MultiPar)secondsvs turbotimesvs par2j (MultiPar)times
verify only7.64±16.0%65.5±0.5%75.6±1.0%8.6x9.9x
118.6±9.0%76.1110±9.4%4.1x5.9x
420.7±18.0%77.3±18.9%118±17.7%3.7x5.7x
1627.9±58.2%84.0±27.4%159±15.8%3.0x5.7x
6464.0±46.2%110±40.2%221±12.5%1.7x3.5x
25647.2±61.9%98.9±27.3%245±15.4%2.1x5.2x
1,02455.81323512.4x6.3x
2,04858.01925073.3x8.8x
4,09667.13118264.6x12.3x
8,19286.056015236.5x17.7x
16,384231106131504.6x13.6x
24,576346158551254.6x14.8x
32,177612209670273.4x11.5x
evidence

Apple M5 Max

cores 18  ·  ram 128.0 GB  ·  os macOS 27.0  ·  set 23 files, 23.0 GiB  ·  blocks 32177  ·  redundancy 100.0%  ·  slice 768000  ·  reps 2  ·  argv r -q -t18 -T18 f.par2  ·  binary 5d0707ee75 (8b0b67ec4d)

Started at 2% foreign CPU on an otherwise idle machine; every repetition agrees to within 5% bar one rung.

parfastpar2cmdline-turbo
blocks to rebuildcountparfastsecondspar2cmdline-turbosecondsvs turbotimes
verify only2.51±0.3%28.1±0.2%11.2x
14.6231.56.8x
45.5532.35.8x
165.5133.16.0x
648.1636.94.5x
2569.2747.25.1x
1,02410.588.58.4x
2,04812.7±14.0%147±6.1%11.6x
4,09615.925816.2x
8,19220.649123.9x
16,38435.497827.6x
24,57668.1147921.7x
32,177134197714.7x
evidence

Apple M3 Ultra

cores 32  ·  ram 256.0 GB  ·  os macOS 27.0  ·  set 23 files, 23.0 GiB  ·  blocks 32177  ·  redundancy 100.0%  ·  slice 768000  ·  reps 2  ·  argv r -q -t32 -T23 f.par2  ·  binary 5d0707ee75 (8b0b67ec4d)

turbo given -T23, the thread count its file list allows rather than a flat -T16. Giving it that costs us about 5% of the ratio at the deepest rung, and it is the fair setting.

parfastpar2cmdline-turbo
blocks to rebuildcountparfastsecondspar2cmdline-turbosecondsvs turbotimes
verify only1.55±0.3%31.0±0.4%20.0x
13.35±6.8%35.010.4x
44.3636.68.4x
164.65±8.4%37.68.1x
646.1741.26.7x
2566.6246.57.0x
1,0247.4666.89.0x
2,0488.4895.811.3x
4,09610.915414.2x
8,19215.427818.0x
16,38427.653419.4x
24,57642.180619.1x
32,17710910729.8x

The everyday repair: 15% parity, where the margin is smallest

This is the floor of the claim, not the claim. At 15% parity a 10 GiB set holds 2,098 recovery blocks, so no repair can go deeper than that, and below about 2,000 blocks parfast's transform has barely started to pay: the whole repair is a few seconds of solve on top of reading the set. The margin here is 1.1x to 6.5x - and it dips lowest in the 64 to 512 block band, where parfast's own cost steps up as it changes strategy - and on the 16-core laptop it is the smallest on this page, because turbo's per-block work spreads across cores well at this depth while parfast is already near its ceiling on six. The last column is the same two tools at the format's ceiling, where the transform is doing the work.

Ratios of medians, par2cmdline-turbo over parfast. Ten 1 GiB files of distinct random data, 750 KiB slices, 13,990 source blocks, 2,098 recovery blocks, seeded scattered damage, two repetitions per rung, the same fixture shape and damage seeds on every box. Seconds, spreads and charts for every machine are behind the toggle.

0x1x2x3x4x5x6x7x116642565121,0242,098blocks that have to be rebuilt (log scale)times slower than parfastM5 Max 6.5xM3 Ultra 6.1xi5 5.3xCore Ultra 9 2.5x
machineverify onlytimes1blocks64blocks256blocks512blocks1,024blocks1,600blocks2,098blocks100% parity, deepesttimes
Intel i5-10600KF2.5x2.0x1.7x1.6x2.5x3.5x4.5x5.3x6.7x at 24,576
Intel Core Ultra 9 386H2.1x2.3x2.3x1.9x1.4x1.6x2.1x2.5x3.4x
Apple M3 Ultra2.3x2.9x2.8x2.7x3.4x4.4x5.3x6.1x9.8x
Apple M5 Max2.4x3.0x2.3x1.8x2.6x4.0x5.7x6.5x14.7x
Show every machine's legs: seconds, spreads and charts
evidence

Intel i5-10600KF

cores 6 / 12 threads  ·  ram 63.9 GB  ·  os Microsoft Windows 11 Pro  ·  set 10 files, 10.0 GiB  ·  blocks 13990  ·  redundancy 14.996%  ·  slice 768000  ·  reps 3  ·  argv r -q -t12 -T16 f.par2  ·  binary cae5a6f368 (8b0b67ec4d)

Three repetitions, started only after the machine had been idle for half an hour and under 3% foreign CPU for ten minutes.

parfastpar2cmdline-turbopar2j (MultiPar)

Reading this. The line stops at 2,098 because that is all the parity this set holds - you cannot rebuild more blocks than you have parity for, so this is the fixture's ceiling and not where the measurement gave up. The deeper charts use a different set. Note the dip between about 64 and 256 blocks, where parfast's own cost steps up as it changes strategy: that is the least flattering stretch of the curve, and a good number of real repairs land in it.

blocks to rebuildcountparfastsecondspar2cmdline-turbosecondspar2j (MultiPar)secondsvs turbotimesvs par2j (MultiPar)times
verify only1.65±0.7%4.12±0.9%9.17±3.8%2.5x5.6x
13.98±6.7%7.87±5.8%16.7±16.6%2.0x4.2x
167.22±78.9%12.4±32.9%39.3±43.2%1.7x5.4x
6410.116.8±56.9%50.0±18.4%1.7x5.0x
25616.326.865.61.6x4.0x
51217.843.586.62.5x4.9x
76819.660.51083.1x5.5x
1,02422.377.31283.5x5.7x
1,15223.985.91393.6x5.8x
1,28023.994.31493.9x6.2x
1,40824.51031604.2x6.5x
1,60025.41151764.5x7.0x
1,79226.41281934.9x7.3x
2,04827.71452155.3x7.8x
2,09828.0±5.0%1482175.3x7.8x
evidence

Intel Core Ultra 9 386H

cores 16  ·  ram 31.4 GB  ·  os Microsoft Windows 11 Home  ·  set 10 files, 10.0 GiB  ·  blocks 13990  ·  redundancy 14.996%  ·  slice 768000  ·  reps 2  ·  argv r -q -t16 -T16 f.par2  ·  binary cae5a6f368

Sole round on that box for its whole window.

parfastpar2cmdline-turbopar2j (MultiPar)
blocks to rebuildcountparfastsecondspar2cmdline-turbosecondspar2j (MultiPar)secondsvs turbotimesvs par2j (MultiPar)times
verify only1.69±2.6%3.55±4.5%10.2±1.2%2.1x6.0x
14.11±43.5%9.56±48.3%23.32.3x5.7x
168.78±17.3%17.446.4±18.3%2.0x5.3x
649.8922.8±14.4%58.82.3x5.9x
25613.4±13.0%25.271.41.9x5.3x
51222.631.3±5.7%89.61.4x4.0x
76823.733.91061.4x4.5x
1,02424.440.01231.6x5.0x
1,15225.642.71321.7x5.2x
1,28025.146.61411.9x5.6x
1,40825.4±11.2%49.41501.9x5.9x
1,60025.854.81632.1x6.3x
1,79227.160.6±7.5%1772.2x6.5x
2,04826.066.01942.5x7.5x
2,09826.867.01972.5x7.3x
evidence

Apple M3 Ultra

cores 32  ·  ram 256.0 GB  ·  os macOS 27.0  ·  set 10 files, 10.0 GiB  ·  blocks 13990  ·  redundancy 14.996%  ·  slice 768000  ·  reps 2  ·  argv r -q -t32 -T16 f.par2  ·  binary 0f859e0c35

Sole round on that box for its whole window.

parfastpar2cmdline-turbo
blocks to rebuildcountparfastsecondspar2cmdline-turbosecondsvs turbotimes
verify only1.49±0.1%3.47±2.7%2.3x
12.216.37±5.6%2.9x
163.089.33±24.5%3.0x
643.30±5.9%9.402.8x
2564.4111.92.7x
5124.6115.7±22.9%3.4x
6404.7516.5±6.6%3.5x
7044.8817.63.6x
7684.9918.73.8x
8965.0020.64.1x
1,0245.1422.7±7.3%4.4x
1,1525.2723.7±6.7%4.5x
1,2805.3026.04.9x
1,4085.4527.2±5.7%5.0x
1,6005.6329.95.3x
1,7925.6734.1±6.0%6.0x
2,0485.9837.0±8.3%6.2x
2,0986.0436.76.1x
evidence

Apple M5 Max

cores 18  ·  ram 128.0 GB  ·  os macOS 27.0  ·  set 10 files, 10.0 GiB  ·  blocks 13990  ·  redundancy 14.996%  ·  slice 768000  ·  reps 2  ·  argv r -q -t18 -T16 f.par2  ·  binary 5d0707ee75

Sole round on that box for its whole window.

parfastpar2cmdline-turbo
blocks to rebuildcountparfastsecondspar2cmdline-turbosecondsvs turbotimes
verify only1.26±0.2%3.04±2.7%2.4x
11.96±6.5%5.793.0x
162.857.072.5x
643.59±6.1%8.232.3x
2567.20±5.1%12.7±5.4%1.8x
5127.54±5.6%19.72.6x
6407.61±5.9%21.92.9x
7047.7924.13.1x
7688.0126.83.3x
8968.0329.63.7x
1,0248.35±6.1%33.84.0x
1,1528.35±5.4%36.74.4x
1,2808.60±6.5%40.14.7x
1,4088.4243.55.2x
1,6008.5148.75.7x
1,7929.0153.55.9x
2,0489.1860.56.6x
2,0989.5161.96.5x

Checking a download before repairing it

A verify reads every file and checks it against the parity set. It is what runs before any repair, and on an undamaged download it is the whole job. Six set shapes on the Intel i5, all seven tools, two repetitions each.

evidence

Six set sizes and shapes

box 6 cores / 12 threads, 64 GB, Windows 11  ·  drive sustained read 0.90 GB/s  ·  reps 2  ·  seconds, median

Read the last two columns before quoting any number in this table. They are the reason it is here.

setparfastseconds turbosecondspar2jseconds par2cmdlinesecondsphpar2seconds rarparseconds vs best rivaltimes read rateGB/sserved from
1 GiB / 1 file1.371.641.981.025.552.660.7x0.78from disk
10 GiB / 10 files1.684.319.778.2252.615.12.6x6.39from RAM
20 GiB / 20 files3.67±7.7%8.7818.016.510530.22.4x5.85from RAM
20 GiB / 1 file23.532.239.318.910553.30.8x0.91from disk
40 GiB / 40 files6.52±38.5%27.0±5.6%41.948.426560.94.1x6.59from RAM
80 GiB / 80 files110±17.6%128±12.2%112±13.7%149±9.7%576266±11.3%1.0x0.78from disk

Your drive decides this, not your memory

The obvious explanation for a verify advantage that fades on large sets is memory - that it lasts while the set fits in RAM and collapses when it does not. That is checkable, and it predicts something specific: two machines with the same processor and different memory should break at different sizes.

They do not. An M1 Ultra with 64 GiB and an M5 Max with 128 GiB, at sizes straddling each machine's own memory:

machinememoryGiBsetGiB parfastsecondsturboseconds ratiotimesread rateGB/s bigger than memory?
Apple M1 Ultra64 GiB10 GiB / 10 files1.773.371.9x6.07no
Apple M1 Ultra64 GiB40 GiB / 40 files3.9610.622.7x10.85no
Apple M1 Ultra64 GiB56 GiB / 56 files6.4816.752.6x9.28no
Apple M1 Ultra64 GiB72 GiB / 72 files9.2523.172.5x8.35yes
Apple M1 Ultra64 GiB96 GiB / 96 files13.5830.832.3x7.59yes
Apple M1 Ultra64 GiB20 GiB / 1 file33.4036.711.1x0.64no
Apple M5 Max128 GiB10 GiB / 10 files1.242.421.9x8.66no
Apple M5 Max128 GiB40 GiB / 40 files3.748.602.3x11.49no
Apple M5 Max128 GiB80 GiB / 80 files6.2215.812.5x13.81no
Apple M5 Max128 GiB120 GiB / 120 files9.2223.582.6x13.98no
Apple M5 Max128 GiB160 GiB / 160 files12.2731.662.6x14.00yes
Apple M5 Max128 GiB200 GiB / 200 files16.5041.062.5x13.02yes
Apple M5 Max128 GiB20 GiB / 1 file23.4826.201.1x0.91no

No cliff, on either machine. The M1 keeps 2.3x on a set half again its memory; the M5 keeps 2.5x on a set 56% bigger than its memory, still reading at 13 GB/s.

It is the drive. On the Intel machine at 80 GiB every tool converged on 0.78 GB/s, which is that drive's sustained read. When the disk is the slowest part it sets the pace for everyone and no amount of CPU shows through. On the Apple machines storage never becomes the slowest part: parfast reaches 13-14 GB/s while turbo sits at 5.2-5.5 GB/s, and the fact that they differ at all is the proof. If the drive were the limit they would be equal.

So the rule is: parfast's verify advantage holds until your storage becomes the bottleneck, and then every tool meets at the floor. Memory matters only because cache can hide a slow disk for a while. It is the drive that decides, and a slow drive reaches that floor at a much smaller set.

This cuts both ways. Most parity sets people actually verify sit comfortably inside the machine verifying them, so the advantage is the common case rather than a laboratory one. But a set larger than your memory on a slow drive is a disk benchmark, whoever runs it, and a ratio quoted without that sentence is worth nothing.

The single-file rows behave the same way on Apple as on Intel - 1.1x on both, at under 1 GB/s. One file is one chain, the parallelism has nowhere to go, and whatever is left is waiting on the device.

Two cases where parfast is slower

At 1 GiB in a single file parfast takes 1.37 s against par2cmdline's 1.02 s, and at 20 GiB in a single file 23.5 s against 18.9 s. Both are single-file sets, and both read at disk speed. A one-file set gives parfast nothing to spread across cores - the work is one chain, and the parallelism that wins the other rows has nowhere to go. The 20 GiB set appears twice in the table on purpose: as 20 files it takes 3.67 s, as one file 23.5 s. Same bytes, same parity, six times the wall - the shape of a set matters more than its size.

Building the parity set, at every size

Ten set sizes from 10 to 80 GiB at three redundancy levels on the M3 Ultra. Building parity is the other job that hurts to wait for, and it is where the memory trade shows: parfast sizes its accumulators from the memory budget, turbo works in small pieces and pays in wall time. The peak columns are the cost of that choice.

These are raw figures with memory unconstrained, which is the number to compare against a rival's own default; parfast's default budget is half the machine and -m is meant to hold it lower. Whether it does was checked rather than assumed: the Core Ultra 9 sweep below ran the identical create under -m2048 as a third arm, and on that machine it did not bind. The table says so.

evidence

Ten set sizes, three parity levels

box M3 Ultra, 32 cores, 256 GB  ·  sizes 10-80 GiB  ·  redundancy 10 / 15 / 20%  ·  slice cap 32,768

The uncapped re-run: turbo at -T32, the box's core count, after the first pass had it at -T16. The capped log is kept and not shown.

set sizeGiBredundancy% source blockscount parfastsecondsturboseconds ratiotimes parfast peakGB of RAM turbo peakGB of RAM
10 GiB10%13,9903.6722.86.2x11.6 GB1.0 GB
10 GiB15%13,9903.9630.07.6x12.2 GB1.5 GB
10 GiB20%13,9904.0639.09.6x12.9 GB2.0 GB
15 GiB10%20,9854.8444.09.1x17.2 GB1.5 GB
15 GiB15%20,9855.2262.512.0x18.2 GB2.3 GB
15 GiB20%20,9855.5582.914.9x19.2 GB3.0 GB
20 GiB10%27,9805.7574.412.9x22.9 GB2.0 GB
20 GiB15%27,9806.1510917.7x24.2 GB3.0 GB
20 GiB20%27,9806.5714321.8x25.3 GB4.0 GB
23 GiB10%32,1776.2796.215.3x26.3 GB2.3 GB
23 GiB15%32,1776.8314120.6x27.7 GB3.5 GB
23 GiB20%32,1776.9618827.0x29.0 GB4.6 GB
30 GiB10%32,7607.7012816.7x34.1 GB3.0 GB
30 GiB15%32,7608.3618722.3x35.9 GB4.5 GB
30 GiB20%32,7608.7324628.2x37.6 GB6.0 GB
40 GiB10%32,76010.617116.1x45.1 GB4.0 GB
40 GiB15%32,76011.424921.8x47.4 GB6.0 GB
40 GiB20%32,76019.232817.1x42.3 GB8.1 GB
50 GiB10%32,75013.921415.4x56.1 GB5.1 GB
50 GiB15%32,75014.831021.0x59.0 GB7.6 GB
50 GiB20%32,75017.641323.4x52.3 GB10.1 GB
60 GiB10%32,76016.325315.5x67.2 GB6.1 GB
60 GiB15%32,76021.536917.2x62.1 GB9.1 GB
60 GiB20%32,76031.349015.7x62.4 GB12.1 GB
70 GiB10%32,76018.829115.5x78.2 GB7.1 GB
70 GiB15%32,76023.043318.8x72.0 GB10.6 GB
70 GiB20%32,76032.257517.9x72.4 GB14.1 GB
80 GiB10%32,72023.233314.3x81.6 GB8.1 GB
80 GiB15%32,72025.449519.5x82.1 GB12.1 GB
80 GiB20%32,72036.066018.4x82.4 GB16.1 GB
evidence

The same sweep on a 31 GB laptop, with a memory-capped arm

Intel Core Ultra 9 386H, 16 cores, 31 GB  ·  sizes 10-40 GiB  ·  redundancy 10 / 15 / 20%  ·  third arm: the identical create under -m2048
set sizeGiBredundancy%source blockscountparfastsecondsparfast -m2048secondsturbosecondsratiotimesparfast peakGB of RAM-m2048 peakGB of RAMturbo peakGB of RAM
10 GiB10%13,99012.213.637.53.1x11.2 GB10.4 GB1.0 GB
10 GiB15%13,99013.515.753.94.0x11.8 GB10.4 GB1.5 GB
10 GiB20%13,99013.815.971.45.2x12.3 GB10.6 GB2.0 GB
15 GiB10%20,98512.814.579.66.2x16.8 GB15.4 GB1.5 GB
15 GiB15%20,98513.414.81188.8x17.6 GB15.6 GB2.3 GB
15 GiB20%20,98514.116.415711.1x18.4 GB15.8 GB3.0 GB
20 GiB10%27,98015.717.91398.9x22.3 GB20.6 GB2.0 GB
20 GiB15%27,98017.418.120912.0x23.5 GB20.8 GB3.0 GB
20 GiB20%27,98017.922.727915.5x21.0 GB21.0 GB3.9 GB
23 GiB10%32,17731.120.01845.9x25.1 GB23.6 GB2.3 GB
23 GiB15%32,17760.822.52844.7x25.0 GB23.9 GB3.5 GB
23 GiB20%32,17722.436.437316.6x24.1 GB24.1 GB3.9 GB
30 GiB10%32,7601661162621.6x25.9 GB25.8 GB3.0 GB
30 GiB15%32,7601331814163.1x25.7 GB25.6 GB3.9 GB
30 GiB20%32,7601401384943.5x25.6 GB25.5 GB3.9 GB
40 GiB10%32,7602042603691.8x25.6 GB25.6 GB3.9 GB
40 GiB15%32,7602182434902.2x25.6 GB25.6 GB3.9 GB
40 GiB20%32,76022124006543.0x25.5 GB26.0 GB3.9 GB

Reading this. One run per cell, so read shapes and not digits. Two things this table says against us, and they stay. First, the memory cap did not cap the create: the -m2048 arm peaks within 1-2 GB of the unconstrained arm at every size, and at 40 GiB and 20% it took 40 minutes against 3.7 for the plain arm - a single run, and a finding to be reproduced before it is explained, but not one to hide. Second, past 23 GiB this 31 GB machine runs out of room for parfast's working set and the wall climbs from seconds to minutes (30 GiB: 133-166 s here against 8 s on the 256 GB M3 Ultra) while turbo, working in small pieces at under 4 GB, climbs far less. The ratio at 30-40 GiB on this box is 1.6-3.0x, not the 15-27x of the big-memory sweep above, and that is the number for a set that does not fit.

Is it worth going past 20% parity?

The protection arithmetic further down says a large set needs more parity than a small one to keep the same real protection. That raises a practical question: what does buying more parity cost? Measured on the M3 Ultra, creating the set.

evidence

20% parity

Apple M3 Ultra, 32 cores  ·  median of 3
set sizeGiBparity% parfastsecondsturboseconds ratiotimes
20 GiB20%6.51142.621.9x
23 GiB20%7.08186.726.4x
30 GiB20%8.66246.328.4x
40 GiB20%13.70328.724.0x
80 GiB20%27.90675.824.2x±28.8%

Reading this. The ratio is not monotone - it peaks around 30 GiB and eases back after. A single multiplier does not describe creation any more than it describes repair, which is why this page keeps showing curves instead of one number.

evidence

25% and 30% parity

Same box, same fixtures  ·  median of 3, repetitions interleaved rather than run back to back

Medians of three interleaved repetitions. parfast's wall-clock spread at 50 and 80 GiB is printed beside those rows: its CPU-seconds are steady there and only the wall moves. turbo's spread never exceeds 6%.

set sizeGiBparity% parfastsecondsturboseconds ratiotimes
10 GiB25%4.3147.511.0x±22.4%
10 GiB30%4.4456.112.6x
23 GiB25%7.18231.432.2x
23 GiB30%7.47283.037.9x
30 GiB25%8.97316.835.3x
30 GiB30%11.32380.433.6x
50 GiB25%18.98533.528.1x±35.3%
50 GiB30%19.91644.632.4x±16.7%
80 GiB25%36.68847.023.1x±18.0%
80 GiB30%38.831008.126.0x±44.9%

Reading this. The consistent part is the shape, and it is visible at every size: raising parity costs parfast very little and costs turbo a great deal. At 23 GiB, going from 20% to 30% parity moves parfast from 7.1 s to 7.5 s and turbo from 187 s to 283 s. parfast's create cost is dominated by the transform, which barely notices the extra recovery blocks; turbo's is dominated by a product that scales with them.

Yes, and it is a normal thing to want

The protection arithmetic says anyone with a set past about 23 GiB who wants real protection has to buy more parity than the customary 15% or 20%. This says that doing so is nearly free on parfast and expensive on everything else - so the region the format pushes large releases into is exactly the region where the gap is widest.

The direction is consistent across five sizes and two parity levels; at 50 and 80 GiB the ratio is a range, 23x to 32x, because of the spreads printed beside those rows.

Fast mode

--fast applies the transform-based solver to the final rebuild, and it is worth more the worse the damage. In 1.5.0 it is on by default on every machine that has a vector kernel for it: all Apple silicon, and any x86 with SSSE3 or newer, which is every PC since about 2006. The flag is kept as an override, and NZBFAST_FORNEY_JOINT=0 in the environment turns it off, which is how the "default" arms on this page were measured. The only builds where it is off are 32-bit ARM (the Raspberry Pi 2 / 3 / Zero 2 W build) and x86 without SSSE3, where no kernel exists for it: the switch is accepted and declines.

Do these numbers understate the version that ships?

Every timing table on this page names its binary in its header line; all but the fast-mode ladders were built on 10 September, before any default flipped. Fast mode is now on by default on every class of machine this page measures, so every repair table here understates the shipping build for repairs past about 1,500 blocks, by the amounts the ladders below give. Nothing has been adjusted upward.

What the switch does on the two Intel machines, on the shipping build. Same fixture on both (32 members, 16,384 blocks at 256 KiB, 100% parity, scattered damage), eleven depths from the first where the switch engages, three repetitions, and an A/A control at every depth so a "change" smaller than the control is noise. Medians of the three:

blocks rebuiltcountIntel i5-10600KF, AVX2 classIntel Core Ultra 9 386H, GFNI class
defaultseconds--fastsecondschangepercentA/Anoisedefaultseconds--fastsecondschangepercentA/Anoise
1,53611.3210.94+3.4%0.4%7.276.88+5.3%0.5%
2,04812.3911.72+5.4%1.5%7.827.16+8.4%2.1%
3,07214.1313.66+3.3%0.7%8.197.76+5.2%0.0%
4,09616.9115.63+7.6%0.6%9.058.18+9.6%0.1%
5,12018.8517.05+9.6%2.3%9.858.62+12.4%0.4%
6,14421.4719.05+11.3%0.8%10.609.21+13.1%0.0%
7,16823.7421.13+11.0%0.1%11.569.98+13.7%0.8%
8,19226.6822.65+15.1%0.1%12.9010.63+17.6%0.2%
10,24032.7727.27+16.8%0.4%15.2812.00+21.5%1.0%
12,28839.5231.87+19.4%8.0%17.7213.67+22.8%3.0%
16,38457.2545.68+20.2%1.0%47.5840.43+15.0%0.8%

Both classes win at every depth, and the win grows with the depth: +2% to +20% on the i5, +4% to +25% on the Core Ultra 9, three of three repetitions at every rung, every rung clearing its own A/A. An earlier build of this switch lost on the i5's class at nine of fourteen depths (worst -12.9% at 5,120 blocks), which is why that class was the last to be switched on: the fix holds the first solver stage on the ordinary arithmetic below the depth where the new kernel starts to pay, and the ladder above is that fix measured on the same machine, fixture and seeds. The pre-fix ladder is kept with the logs.

The Apple figures do understate, by a measured amount. Same fixture, three repetitions, an A/A control at every depth:

M1 Ultra +0.4% at 256 blocks rising to +20.7% at 16,384. M3 Ultra +0.8% rising to +20.0%. Near nothing at the shallow end, about a fifth off the deep repairs.

Because the i5's loss sits between the depths those ladders sampled, the same band was re-measured on three Apple parts at half steps - an M5 Max and two M1 Ultras, nine depths from 2,048 to 6,144, three repetitions each, an A/A control at every depth - looking for a loss the coarser ladders could have stepped over. There is none: across 27 depth-medians the worst is -2.6% (0.1 s, on the M5 at 4,608) and the best +5.3%, and every negative sits inside its own machine's A/A of ±0.8 to 1.8%. The Apple default holds where the AVX2 one does not.

That is not a licence to add 20% to the deepest rows. Those ladders stop at 16,384 blocks and the Apple tables run to 32,177; on the one machine measured past that band, an AMD Zen 5, the gain fell from +32.7% at 12,288 to +4.5% at 16,384. Nothing on this page has been adjusted upward.

evidence

Which machines it works on at all

capability
test one repair at m=16,384 on a 32,768-block set, reading the engine's own stage-1 label  ·  engaged = the joint kernel ran  ·  fell back = the switch was accepted and the ordinary solver ran anyway
machinevector feature that decides itresulthow we know
Apple M1 / M3 / M5, every variantNEON, always sufficient engagesmeasured, M3 Ultra
Intel and AMD x86 without GFNIAVX2 nibble kernel engagesmeasured, Intel i5-10600KF
Intel and AMD x86 with GFNIthe GFNI kernel engagesmeasured, Intel Core Ultra 9 386H and AMD Ryzen 9800X3D
Older x86 with SSSE3 but no AVX2 - pre-2013 Atom, Celeron, NAS boxes a 128-bit SSSE3 kernel engagesderived from the source; no such part was available to test
32-bit ARM - the Raspberry Pi 2 / 3 / Zero 2 W build no vector kernel on that architecture does not engagederived from the source

Why a bigger file is a less protected file

This is the reason the repair rounds go past 20% redundancy, and the reason the full-range fixture is 23 GiB rather than a rounder number. It is arithmetic, not measurement - two constants from the PAR2 spec produce every line below.

Where this comes from

A PAR2 set is capped at 32,768 input slices, and a slice must be a multiple of 4 bytes (MAX_INPUT_SLICES, crates/nzbkit-base/src/par2gen.rs). The cap is on the count, not the size, so past a certain set size the slice has to grow - there is no other way to stay under it.

Damage on Usenet arrives one article at a time, and a poster sizes an article at roughly 768,000 bytes. A block is only repairable whole, so one lost article destroys one whole slice, however big that slice is. While a slice is one article, that is an even trade. Once a slice is four articles, every single lost article burns four articles' worth of recovery capacity.

So the share of articles you can afford to lose is not the parity percentage. It is parity x (article / slice), and past the knee it falls in exact proportion to the set size.

23.44 GiB is where it starts to bite

32,768 slices x 768,000 bytes = 25,165,824,000 bytes = 23.44 GiB (25.2 GB). Up to there a slice can stay the size of one article and 20% parity really does mean you can lose 20% of the articles. One byte past it, the slice has to grow and the protection starts falling. It is the largest set that gets the protection its parity setting advertises - which is exactly why the full-range benchmark fixture is 23 GiB.

evidence

How much you can lose and still recover

arithmetic
from MAX_INPUT_SLICES = 32,768  ·  article 768,000 bytes  ·  knee 23.44 GiB
20% parity10% parity30% parity

Reading this. Arithmetic, not measurement - two constants from the PAR2 spec produce every line, and no tool was run. It describes scattered article loss, the common case; a contiguous loss of one whole file is still covered by r% parity at any slice size. The flat stretch on the left is the whole range where the parity setting means what it says. The plot stops at 100 GiB so the 5 to 100 GiB band is readable at all; the arithmetic runs to 1 TiB and the table below carries every row.

evidence

How much parity you need to stay just as safe

arithmetic
same two constants  ·  read as: parity = target x set size / 23.44 GiB
to hold 20%to hold 10%

Reading this. The same arithmetic, read backwards: how much parity you must buy to keep a fixed level of protection as the set grows. Nobody posts 85% parity; past the knee the practical choice is to accept less protection or to split the release into smaller sets. The plot stops at 100 GiB, where holding 20% already costs 85% parity. It carries on to 853% at 1 TiB, which is in the table and would flatten everything else if it were drawn.

Read the other way round: to keep a 20% article-loss tolerance you have to buy parity in proportion to how far past the knee you are. At 100 GiB that is 85% parity - 85 GiB of recovery data for a 100 GiB set. At 200 GiB it is 171%, which is more parity than payload. This is where the judgement call lives: nobody posts 85% parity, so in practice you accept less protection, or you split the release into sets that each stay near the knee.

set sizeGiBslice sizeMB source blockscount articles you can lose at 20% parity% of articles parity needed to hold 20%% of payload
5.00 GiB0.73 MB6,99120.00%20.0%
10.00 GiB0.73 MB13,98220.00%20.0%
15.00 GiB0.73 MB20,97220.00%20.0%
20.00 GiB0.73 MB27,96320.00%20.0%
23.44 GiB0.73 MB32,76820.00%20.0%
30.00 GiB0.94 MB32,76815.62%25.6%
50.00 GiB1.56 MB32,7689.38%42.7%
75.00 GiB2.34 MB32,7686.25%64.0%
100.00 GiB3.12 MB32,7684.69%85.3%
150.00 GiB4.69 MB32,7683.12%128%
200.00 GiB6.25 MB32,7682.34%171%
300.00 GiB9.38 MB32,7681.56%256%
500.00 GiB15.62 MB32,7680.94%427%
750.00 GiB23.44 MB32,7680.62%640%
1 TiB31.25 MB32,7680.47%853%

What this calculation does not cover

It describes scattered damage - articles going missing here and there, which is the common case and the one that gets worse. It does not describe a contiguous loss, such as one whole file of a set being unavailable: there, r% parity covers r% of the volume whatever the slice size, because the lost articles fall inside the same slices rather than each spoiling a fresh one. The collapse is a granularity effect, not a capacity one.

It also assumes a poster who matched the slice to the article, which is the good case. A slice that straddles article boundaries does slightly worse than these lines, never better.

What it means for the numbers on this page

Every answer to the collapse makes the repair job harder, not easier. More parity means more recovery blocks to compute on create and more to solve on repair. Splitting into more sets means more sets to verify. Accepting the loss in protection means that when damage does arrive it is more likely to need a deep repair rather than a shallow one. That is the work the ladders measure, and it is why stopping the measurements at 20% redundancy and 2,098 blocks would have left out the cases people will actually hit.

How these were measured

Every repair is checked, never trusted

Every repair is checked by SHA-256 of all members against a gold manifest taken before damage. An exit code cannot stand in for it: par2j returns 16 on a successful repair, so anything that treats a zero exit as success silently discards every par2j result while appearing to work.

Every tool got the same command, and its best settings

Both tools get the same -t and -T on every leg. -T is file-hash parallelism and it cannot profitably exceed min(cores, files); parfast takes that by default, turbo has to be told. A flat -T16 was used at first, which capped turbo on the two boxes with more than 16 cores. That runs the dangerous way - it understates the competitor and inflates our ratio - so both affected rounds were re-run uncapped and the re-runs are what this page shows: the M3 full range at -T23 (turbo's deepest leg went from 1,122 s to 1,072 s, our ratio from 10.3x to 9.8x) and the M3 create sweep at -T32. The capped logs are kept on disk and not published. The ladders are unaffected: with ten members, 16 cannot bind.

Medians, and the spread behind them

Every figure is the median of the repetitions, and where the repetitions differ by 5% or more the spread is printed next to it in red, so a median cannot hide a swing. Reading those spreads turned up one real bias: the first repetition is systematically slower than the second on the boxes short of memory (1.66x over the first four rungs on the 64 GB i5, 1.14x on the 31 GB laptop, flat on the 128 GB and 256 GB Apple machines). That is a cold page cache and the write-back from set creation, not the tool. It runs in our favour to report it, since the cold pass costs parfast more than it costs turbo, so the small-job ratios are conservative; it is still wrong, and every round now starts with an untimed warm-up pass and repeats any rung whose repetitions disagree by 10% or more, up to five times while its legs stay under two minutes.

How much the repetitions disagree

Counted for every machine from the same rows the tables show:

machinerungs comparedcount disagree by 5%+rungsby 15%+rungs by 30%+rungsworst% spread
Intel i5-10600KF4296479%
Intel Core Ultra 9 386H4294248%
Apple M3 Ultra34102024%
Apple M5 Max349006%

The i5's worst is the cold first repetition at 64 blocks. A leg counts only under the round's declared command line, so a six-leg par2j thread-count probe on that machine is excluded from its 1,024 row. One lock holds each machine, and every leg samples the CPU used outside its own process tree and refuses to start above 10% of the box, waiting and retrying before it gives up; a leg measured beside somebody else's work is not slow, it is wrong, and the hash gate cannot tell.

What is not here

No extrapolated points, no fitted curves and no gap filling. A rung with no measurement is absent rather than estimated, and a round that was spoiled by another job on the same machine is thrown away rather than published with a caveat.