Five clients, eight scenarios, identical hardware and providers, runs interleaved so provider drift cancels. The metric is time to a usable file: downloaded, verified, extracted. Includes the legs we don't win.
On this page
Methodology first
pipelining_requests=8 (it ships 1, i.e. unpipelined; that setting alone took its 190 GB time from 24m24s to 19m02s), NZBGet got ArticleCache/DirectWrite/DirectUnpack/ParQuick, rustnzb its documented config.Scenario 1 · clean, huge
| nzbfast | NZBGet 26.2 | SABnzbd 5.0.4 | rustnzb 1.3.4 | |
|---|---|---|---|---|
| time to usable file | 4m 33s | 7m 58s (+75%) | 19m 32s (+329%) | none¹ |
| GB on the wire | 169.6 | 169.8 | 169.7 | 186.5 |
| peak RSS | 1.4 GB² | 1.5 GB | 1.8 GB | 0.6 GB |
¹ rustnzb finished moving bytes at 5m 42s having pulled 186.5 GB (10% more wire than anyone) but left no extracted media, its third straight failed round on this post. · ² nzbfast's memory follows its configured budget, not the job: this round ran the default auto budget and peaked at 1.4 GB; a deliberately huge 64 GB budget buys only 4% (4m 22s), and capped at 1 GB the same 190 GB job still completes (see the low-memory ladder below). On the earlier East Coast round (~2.4–3 Gbps line) the same scenario ran 9m 00s vs NZBGet +30% and SABnzbd +111%. The gap holds across line speeds.
Scenario 2 · the gap grows with size
One-pass means no post-download verify/unpack pass, so the bigger the job, the further ahead it lands. Same-machine sequential runs:
| Job | nzbfast | NZBGet | SABnzbd |
|---|---|---|---|
| 7.4 GB REMUX (Europe, 10 GbE) | 13.7 s | 17.3 s (+26%) | 19.0 s (+39%) |
| 35 GB obfuscated 4K (Europe) | 67 s | 108 s (+61%) | 285 s (+325%) |
| 87 GB 4K (East Coast) | 272 s | 370 s (+36%) | 708 s (+160%) |
| 87 GB on a 97 GB-free disk (Europe) | 3m 08s | cannot run² | cannot run² |
| 190.6 GB (East Coast) | 9m 00s | 11m 43s (+30%) | 19m 02s (+111%) |
² Their peak footprint (volumes + unpacked output simultaneously, ~156 GB) exceeded the 97 GB free. One-pass needs 1× the content size: it halves the disk you need, not just the time.
Scenario 3 · obfuscated post
| nzbfast | NZBGet | SABnzbd | rustnzb | |
|---|---|---|---|---|
| time to usable file | 96 s | 153 s (+59%) | 259 s (+170%) | no usable file³ |
| peak RSS | 1.55 GB | 3.7 GB | 8.8 GB | 3.6 GB |
³ rustnzb downloaded in 119 s, marked the job Completed, and shipped the raw obfuscated volumes: no rename, no extraction. nzbfast deobfuscated from PAR2 metadata and extracted in-stream, zero read-back blocks.
Scenario 4 · queue of three
| nzbfast | rustnzb | NZBGet | SABnzbd | |
|---|---|---|---|---|
| time to finish the queue | 122 s | 136 s | 162 s | 277 s |
| line idle (<20 MB/s) | 2 s (2%) | 16 s (12%) | 0 s | 168 s (61%) |
Three shapes of the same problem: nzbfast's tail-overlap keeps the line busy edge-to-edge; NZBGet never idles but runs ~35% slower while unpacking concurrently; SABnzbd downloads fast, then leaves the line dark 61% of the time during serial post-processing. In the resilience variant (one job with encrypted RAR headers), SABnzbd's queue wedged on the encrypted job and only 1 of 3 jobs ever completed; nzbfast parked it with a clear message and finished the rest.
The honest column
Both legs that used to sit here have been re-measured on the shipping build and neither is a loss any more: the damaged store-mode post now takes us 30 s against NZBGet's 38 s, and par-only reconstruction now completes in 9 s where it took 19 s, on a leg where NZBGet returns in the same time but delivers nothing. We are leaving the section here rather than deleting it. This is where our losses go, and the next round that finds one will put it back.
Scenario 6 · starve it of RAM
The same four jobs, re-run at hard memory budgets of 2 GB, 1 GB and 256 MB: what the auto-sizer would pick on an 8 GB box, a 4 GB box, and a 2 GB NAS. Every leg produced a correct, fully verified, extracted file; peak RSS tracked the budget, not the job. Time to usable file, 10 GbE line:
| Job size | plenty of RAM | 2 GB budget | 1 GB budget | 256 MB budget |
|---|---|---|---|---|
| 7 GB | 15 s | 15 s | 15 s | 15 s |
| 35 GB | 65 s | 70 s | 70 s | 65 s |
| 87 GB | 148 s | 206 s | 196 s | 180 s |
| 190 GB | 330 s | 427 s | 402 s | 411 s |
The 20–40% premium on the big jobs is a 10 GbE artifact: spilled blocks only cost time when the line outruns the disk. The same 87 GB job at the same budgets on a ~2.4 Gbps line measured −1% to +7%, noise. On a typical home connection a small budget is close to free at any job size. A NAS profile (2 connections, 256 MB budget) finished the 35 GB job in 0.4 GB peak RSS. A 2 GB NAS can run this. No other client offers a memory ceiling at all.
Scenario 7 · archives inside archives
Posts increasingly arrive nested: a RAR inside a RAR, a 7z tucked into a store archive, a ladder of layers, a password chain. This round grades what's left for the operator. auto means every payload extracted, byte-identical, no hands; manual means the client reported success but left an inner archive sitting in the output directory for you to open yourself.
| shape | nzbfast | SABnzbd | NZBGet | rustnzb |
|---|---|---|---|---|
| store RAR inside store RAR | auto | auto | manual | manual |
| compressed RAR inside store RAR | auto | auto | manual | manual |
| 7z inside a store RAR | auto | auto | manual | manual |
| 5-level ladder, 6 payloads | auto · 6/6 | manual · 3/6 | manual · 1/6 | manual · 1/6 |
| password chain, 3 encrypted levels | auto · 3/3 | asks for a password | asks for a password | failed |
| auto-complete, all ten shapes | 8/10 | 6/10 | 2/10 | 2/10 |
Loopback rig, machine-generated corpus, all four clients on the same machine, graded by content hash, so a client that renames the payload still gets credit. Because inner layers are denested on the fly, nzbfast holds one ~1.5 GB copy on disk where write-out-and-unpack clients hold ~3 GB, and finishes these legs in 1–2 s against 4–8 s. On the password chain, each layer's password ships in a file the layer above it extracts: nzbfast reads it and unlocks all three levels; the others stop and wait for you to type it. The two shapes it doesn't auto-complete are graded harshly on purpose: a 10-level ladder past its default depth cap and a post damaged at all three levels. On both it recovers more payloads than any other client, but exits nonzero instead of calling a partial job a success, so both count as failures here.
What a job costs you
The one-pass claim is about disk as much as speed, so this is it measured rather than asserted: the highest the working directory ever got during the nested runs, polled twice a second. Reading it once at the end would be meaningless, because a client that deletes its volumes after extracting would look like it never wrote them.
| shape | nzbfast | NZBGet 26.2 | rustnzb 1.3.4 | SABnzbd 5.0.4 |
|---|---|---|---|---|
| store RAR inside store RAR | 1538 | 1538 | 1774 | 3080 |
| compressed inner layer | 1536 | 1536 | 1674 | 3102 |
| RAR inside RAR, depth 2 | 1536 | 1536 | 1714 | 3076 |
| 7z wrapped in a store RAR | 1503 | 1536 | 1722 | 3102 |
Megabytes, lower is better. NZBGet matches us here
and it is worth saying why: it is running with DirectUnpack and
DirectWrite on, which is how we configure every competitor, and on these shapes
that is enough to reach one copy on disk. SABnzbd holds two. The gap that remains is the one
the pipeline was built for: we never materialise the volumes at all, so the peak is the payload
itself rather than the payload plus the archive that carried it.
Scenario 8 · five clients, reproducible content
Every leg above runs against commercial providers, so you have to take our word for the line conditions. This one you can rebuild yourself: the content is Blender's open movies (Tears of Steel 4K, Sintel, Big Buck Bunny 4K at 60 and 30 fps), CC-BY 3.0, packed store-mode RAR plus 10% PAR2 into 53 files and 14,521 articles, served over loopback NNTP from RAM by a rig in this repository. No provider is involved, so this measures the client itself, with provider variance removed rather than averaged out.
Because the articles come from memory, the absolute times are far shorter than any real download and are not comparable to the provider legs above. Read the ratios and the disk column, not the seconds.
| client | time to finish | connections | peak disk | vs nzbfast |
|---|---|---|---|---|
| nzbfast | 5 s | 8 | 8.6 GB | baseline |
| Weaver (warmed) | 8 s | 120 (auto-ramp) | 17.9 GB | 1.6× slower |
| NZBGet 26.2 | 12 s | 16 | 17.6 GB | 2.4× slower |
| SABnzbd 5.0.4 | 14 s | 8 | 17.6 GB | 2.8× slower |
| rustnzb 1.3.4 | 23 s | 8 | 18.7 GB | 4.6× slower |
Time to finish runs from starting the job to all four videos being on disk, verified and extracted. Peak disk is the most disk the client ever occupied at any instant, sampled twice a second, and it is the column that matters most here: one-pass needs about 1× the content, everything else about 2×. All five ended holding the same 8.6 GB once they had tidied up, which is exactly why the peak is the interesting figure. Every client produced all four payloads sha256-identical to source. Each is shown at whichever connection count made it fastest (8, 16 and 32 were tried on each; nzbfast was flat at all three, so more connections would not have helped it).
Every competitor at its documented best. A
rival must never lose because we misconfigured it, so each client's settings are published with
the round. Two are easy to get wrong and worth knowing if you run your own: SABnzbd rewrites its
own ini at startup and reverts pipelining_requests to the shipped 1, so
pipelining has to be set over the API afterwards and read back to confirm; and a standalone
NZBGet -c config inherits NZBGet's built-in defaults rather than the values in its
shipped conf, which silently leaves the article cache off. Both ran with those corrected. Weaver
is measured warm, because it auto-ramps its connection count and tunes its pools on the first job
and its download CLI never exits, so it runs as a persistent daemon with a discarded
warm-up pass. Its 8 s is therefore a warmed daemon at 120 connections against our cold one-shot
at 8. That is each client at its best by our own rule, but the asymmetry is real and we would
rather state it than bury it.
Peak disk is polled twice a second rather than read once at the end, which matters more than it sounds: every client here deletes its volumes after extraction, so all five finish holding the same 8.6 GB and four of them look one-pass if you only measure the aftermath. Polled through the run, four peak near 18 GB. For anything that self-cleans, report the peak, not the leftovers.
Component shootouts
Repair (PAR2) and unpack (RAR) are our own native code rather than bundled third-party binaries, so we also race them standalone against the dedicated tools on identical corpora, on three machines spanning what a reader might actually own. A time only counts when the output is byte-identical to the source payload: every RAR figure below was sha256-checked against the source, and every repaired file against the pristine set.
Each bar is our time as a fraction of
unrar 7.23, RARLab's own reference implementation and the fastest of the field on most
shapes. Full track = unrar. 32-core desktop, best of 3, tools interleaved inside each round.
Seven bars, not eight: RAR4 cannot be created by rar 7.x, so that shape ran on the
laptop only and is in the table below.
The whole field, seconds, lower is better.
The same archive shapes on all three machines, seven on the desktops and eight on the laptop.
Archives were created by official rar 7.23 so no tool is judged on input from its
own encoder. rarpar is Weaver's own RAR and PAR2 code, built from source at
a5de0d3; we pin the commit rather than a version because its crates carry three
different version numbers.
| shape | nzbfast | unrar 7.23 | rarpar | unar | rars 0.4.7 | bsdtar |
|---|---|---|---|---|---|---|
| High-end desktop, 32 cores | ||||||
| store 200 MB | 0.05 | 0.05 | 0.05 | 0.12 | 0.14 | 0.07 |
| big, 3 volumes | 0.47 | 0.73 | 0.74 | 2.12 | 2.45 | wrong output² |
| 400 small files | 0.07 | 0.30 | 0.35 | 1.24 | 1.35 | 2.37 |
| solid | 0.15 | 0.33 | 0.38 | 1.29 | 1.84 | 2.39 |
| repetitive | 0.03 | 0.04 | 0.03 | 0.08 | 0.14 | 0.19 |
| encrypted | 0.48 | 0.79 | 0.73 | 2.91 | 5.88 | unsup |
| 128 MB dictionary | 0.70 | 0.90 | 0.96 | 2.63 | 2.83 | unsup |
| Older desktop, 20 cores | ||||||
| store 200 MB | 0.05 | 0.05 | 0.06 | 0.14 | 0.16 | 0.07 |
| big, 3 volumes | 0.59 | 1.02 | 0.89 | 2.59 | 3.08 | wrong output² |
| 400 small files | 0.09 | 0.39 | 0.44 | 1.45 | 1.72 | 2.81 |
| solid | 0.19 | 0.42 | 0.47 | 1.49 | 2.43 | 2.84 |
| repetitive | 0.03 | 0.05 | 0.04 | 0.10 | 0.17 | 0.22 |
| encrypted | 0.60 | 1.12 | 0.92 | 3.64 | 7.56 | unsup |
| 128 MB dictionary | 0.78 | 1.27 | 1.11 | 3.09 | 3.44 | unsup |
| Laptop, 14 cores / 20 threads, Windows⁴ | ||||||
| store 200 MB | 0.08 | 0.16 | 0.16 | no CLI | 0.24 | 0.17 |
| big, 3 volumes | 0.66 | 1.28 | 1.10 | no CLI | 6.16 | wrong output² |
| 400 small files | 0.29 | 1.29 | 2.14 | no CLI | 4.26 | 2.27 |
| solid | 0.71 | 1.62 | 2.15 | no CLI | 20.91 | 2.75 |
| repetitive | 0.07 | 0.14 | 0.09 | no CLI | 0.28 | 0.14 |
| encrypted | 0.66 | 1.30 | 1.13 | no CLI | fail | unsup |
| RAR4 | 0.89 | 1.51 | reject³ | no CLI | 2.30 | reject³ |
| 128 MB dictionary | 0.85 | 1.42 | 1.32 | no CLI | 7.55 | unsup |
The margins are widest on the laptop, not the
32-core box: small-files 4.4× and solid 2.3× there versus unrar. The parallel decode paths scale
into threads that a single-threaded extractor cannot use, so the gap grows on modest hardware
rather than shrinking. rars 0.4.7 is the upstream crate we forked, shown
unmodified: our fork is 3× to 16× faster than it, which is the extraction work in one column.
² bsdtar has no RAR5 multi-volume support and silently produced a truncated file, so that leg is
a correctness failure, not a slow time. ³ rar 7.x can no longer create RAR4, so
that one archive comes from the rars encoder (unrar-validated); several tools reject it, and it
is the one shape the two desktop rounds could not rebuild, so it appears on the laptop only.
⁴ unar has no Windows CLI, so the laptop field is five tools.
Dates, because they are not all the same. The two desktop groups were re-measured for 1.0.8 on one freshly built corpus, with every tool run from the same staged binaries so no machine raced a different version. The laptop group is the earlier round and is unchanged. That is deliberate rather than lazy: extraction performance did not move between 1.0.7 and 1.0.8, which we checked by racing both builds head to head on every shape and finding them level, so the laptop figures still describe the shipping build. Re-running that rig would have changed the corpus without changing the answer.
Corpus: 1 GiB payload packed store-mode into 21 RAR volumes, then a classic PAR2 set at 1 MiB blocks and 10% redundancy, then a fixed 101-block damage map across 6 volumes for the repair leg. Bars are scaled within each machine, since the hardware differs. Lower is better.
High-end desktop, 32 cores
Older desktop, 20 cores
Laptop, 14 cores, Windows
High-end desktop, 32 cores
Older desktop, 20 cores
Laptop, 14 cores, Windows
Fastest verify and fastest repair on all three
machines, against the SIMD par2cmdline-turbo fork, classic
par2cmdline 1.2.0 and MultiPar's par2j. Every repaired volume came out
byte-identical to the pristine set. The gap is widest on the desktops because our repair path
spreads the Reed-Solomon fold across cores; on 14 cores it is 1.4× rather than 2×. Weaver's
rarpar was raced on the two desktops as well and lands behind classic
par2cmdline on repair: 4.91 s and 5.87 s against our 0.88 s and 1.28 s.
⁵ par2j verifies this set fine but returned a non-zero status on the repair leg in
our harness; it likely wants a different invocation and we did not chase it, so read that row as
"not measured", not as a failure of MultiPar.
Light damage, the common field case. A handful of failed articles is far more typical than 101 dead blocks, so this round adds a 3-block repair leg: 0.58 s against par2-turbo's 1.12 s on 32 cores, 0.69 s against 1.37 s on 20 cores. It is worth saying what did not move. The 1.0.8 repair rewrite spreads the fold across rows and columns, and rows are the missing-block count, so light damage is exactly where the old code left a big machine idle. In the fold microbenchmark alone that is a 3.65× speedup. End to end it is worth almost nothing, because the fold is about a millisecond of a run dominated by reading and MD5-ing a gigabyte. Both halves are true and the second one is the one that reaches users.
When PAR2 cannot cover the damage, the
recovery record inside the RAR itself is the last line of defence. Until 1.0.8 ours failed on any
archive over about 13 MB, so this leg could not be run at all. Damage is three 3,000-byte holes at
20%, 50% and 80% through the protected region. Both tools produced output byte-identical to the
pristine file, and ours is byte-identical to what rar r itself writes.
| archive | nzbfast | rar 7.23 repair | |
|---|---|---|---|
| 16 MB | 0.15 | 0.26 | 1.7× faster |
| 32 MB | 0.26 | 0.44 | 1.7× faster |
| 128 MB | 0.89 | 1.03 | 1.2× faster |
| 512 MB | 3.46 | 2.23 | 1.6× slower |
We lead to about 128 MB and RARLab pulls ahead by 512 MB, so the crossover sits somewhere in the low hundreds of MB. That last row is a loss and it stays on the page: our repair streams rather than holding whole volumes in memory, which costs throughput at the top end and buys a bounded working set. On the 8 GB to 20 GB volumes a daemon actually meets, holding the volume is not an option, so it is the right trade even where it loses. Measured against the buffered path on the same archive: 1.4× slower to run, 2.3× less peak memory.
What else moved in 1.0.8, and where it does not
show. Three more engine changes landed that these corpora cannot see, listed here so the
numbers above are not read as the whole story: rebuilding a .rev volume now does one
erasure solve instead of one per byte; RAR5 archives with tens of thousands of members resolve
each member once rather than walking the list per worker (3× less processor time at 40,000
members); and the RAR1.3 bit reader works a word at a time (2×). None of them appear above,
because the shapes here have 400 members, no .rev set, and no RAR1.3.
What we deliberately do not do: we never create PAR2. A downloader has no reason to, and ParPar owns that leg. We also buy speed with memory on both engines: extraction peaks around 240 MB against unrar's 41 MB, and verify around 126 MB against turbo's 7 MB, because these are the inline engines that ride a live download rather than standalone one-shots. If you want the smallest possible resident set for a standalone job, the dedicated tools still win that column.
Capability, not micro-benchmarks
| nzbfast | SABnzbd 5 | NZBGet 26 | rustnzb | Usenapp | Newsbin | |
|---|---|---|---|---|---|---|
| pipelined NNTP | yes | off by default | no | yes | - | - |
| full verify during download | every block | after | quick-check | after | after | after |
| extract during download | in-stream, no volumes on disk | direct unpack⁴ | direct unpack⁴ | unreliable⁵ | no | no |
| disk needed for an N-GB post | ~1×N | ~2×N | ~2×N | ~2×N | ~2×N | ~2×N |
| pre-download completability verdict | block-exact | no | health % | no | article check | no |
| bounded memory (never swap) | budgeted | 9.3 GB @ 190 GB | cache setting | no | - | - |
| check the file at any point while downloading | yes | no | no | no | sequential | no |
| built-in indexer + poster wall | yes, keyless | no | no | no | search UI | group browser |
| Sonarr/Radarr drop-in | SAB API + Newznab | native | native | partial | no | no |
| phone remotes (nzb360/LunaSea) | via NZBGet RPC | yes | yes | no | no | no |
| watchlist auto-grab + upgrades | built in | via *arr | via *arr | no | Watchdog | rules |
| single self-contained binary | yes | Python | yes | yes | .app | .exe |
| open source | GPL⁶ | GPL | GPL | yes | paid | paid |
| platforms | mac/win/linux/docker | mac/win/linux | mac/win/linux | linux/win | mac only | win only |
⁴ Direct unpack still materialises the volumes first: 2× writes and 2× disk. ⁵ rustnzb shipped obfuscated volumes marked "Completed" in our round (its unpack also hangs with RARLab unrar unless disabled). ⁶ GPL-3.0-or-later. Usenapp/Newsbin are single-platform commercial readers with downloader features; they're listed because people ask, not because they compete on speed.
Transport proof