Quatre clients, sept scénarios, matériel et fournisseurs identiques, exécutions entrelacées pour que la dérive des fournisseurs s’annule. La métrique est le temps jusqu’à un fichier utilisable : téléchargé, vérifié, extrait. Y compris les manches que nous ne gagnons pas.
Sur cette page
La méthodologie d’abord
pipelining_requests=8 (il est livré avec 1, c’est-à-dire non pipeliné ; ce seul réglage a fait passer son temps sur 190 GB de 24m24s à 19m02s), NZBGet a reçu ArticleCache/DirectWrite/DirectUnpack/ParQuick, rustnzb sa config documentée.Scénario 1 · propre, énorme
| nzbfast | NZBGet 26.2 | SABnzbd 5.0.4 | rustnzb 1.3.4 | |
|---|---|---|---|---|
| temps jusqu’au fichier utilisable | 4m 33s | 7m 58s (+75%) | 19m 32s (+329%) | aucune¹ |
| GB sur le fil | 169.6 | 169.8 | 169.7 | 186.5 |
| pic de RSS | 1.4 GB² | 1.5 GB | 1.8 GB | 0.6 GB |
¹ rustnzb a fini de déplacer des octets à 5m 42s après avoir tiré 186.5 GB (10% de fil de plus que tout le monde) mais n’a laissé aucun média extrait, sa troisième manche échouée d’affilée sur ce post. · ² la mémoire de nzbfast suit son budget configuré, pas la tâche : cette manche a tourné avec le budget auto par défaut et a culminé à 1.4 GB ; un budget délibérément énorme de 64 GB ne gagne que 4% (4m 22s), et plafonnée à 1 GB, la même tâche de 190 GB se termine quand même (voir l’échelle basse mémoire ci-dessous). Lors de la manche antérieure sur la côte Est (ligne ~2.4–3 Gbps), le même scénario a tourné en 9m 00s contre NZBGet +30% et SABnzbd +111%. L’écart tient à toutes les vitesses de ligne.
Scénario 2 · l’écart croît avec la taille
Une passe signifie aucune passe de vérification/extraction après téléchargement, donc plus la tâche est grosse, plus l’avance se creuse. Exécutions séquentielles sur la même machine :
| Tâche | nzbfast | NZBGet | SABnzbd |
|---|---|---|---|
| REMUX de 7.4 GB (Europe, 10 GbE) | 13.7 s | 17.3 s (+26%) | 19.0 s (+39%) |
| 4K obfusqué de 35 GB (Europe) | 67 s | 108 s (+61%) | 285 s (+325%) |
| 4K de 87 GB (côte Est) | 272 s | 370 s (+36%) | 708 s (+160%) |
| 87 GB sur un disque avec 97 GB libres (Europe) | 3m 08s | impossible² | impossible² |
| 190.6 GB (côte Est) | 9m 00s | 11m 43s (+30%) | 19m 02s (+111%) |
² Leur empreinte maximale (volumes + sortie extraite en même temps, ~156 GB) dépassait les 97 GB libres. Une passe n’exige que 1× la taille du contenu : elle divise par deux le disque nécessaire, pas seulement le temps.
Scénario 3 · post obfusqué
| nzbfast | NZBGet | SABnzbd | rustnzb | |
|---|---|---|---|---|
| temps jusqu’au fichier utilisable | 96 s | 153 s (+59%) | 259 s (+170%) | aucun fichier utilisable³ |
| pic de RSS | 1.55 GB | 3.7 GB | 8.8 GB | 3.6 GB |
³ rustnzb a téléchargé en 119 s, a marqué la tâche Terminée, et a livré les volumes obfusqués bruts : aucun renommage, aucune extraction. nzbfast a désobfusqué à partir des métadonnées PAR2 et extrait au fil du flux, zéro bloc relu.
Scénario 4 · file de trois
| nzbfast | rustnzb | NZBGet | SABnzbd | |
|---|---|---|---|---|
| temps mural de la file | 122 s | 136 s | 162 s | 277 s |
| ligne inactive (<20 MB/s) | 2 s (2%) | 16 s (12%) | 0 s | 168 s (61%) |
Trois formes du même problème : le recouvrement de queue de nzbfast garde la ligne occupée d’un bout à l’autre ; NZBGet n’est jamais inactif mais tourne ~35% plus lentement en extrayant en parallèle ; SABnzbd télécharge vite, puis laisse la ligne éteinte 61% du temps pendant un post-traitement sériel. Dans la variante de résilience (une tâche avec des en-têtes RAR chiffrés), la file de SABnzbd s’est coincée sur la tâche chiffrée et seule 1 tâche sur 3 s’est terminée ; nzbfast l’a garée avec un message clair et a fini le reste.
La colonne honnête
Les deux manches qui figuraient ici ont été remesurées sur la version publiée et aucune n'est plus une défaite : le post store-mode endommagé nous prend maintenant 30 s contre 38 s pour NZBGet, et la reconstruction par parité seule s'achève en 9 s au lieu de 19 s, sur une manche où NZBGet répond dans le même temps mais ne livre rien. Nous laissons la section en place plutôt que de la supprimer : c'est ici que vont nos défaites, et la prochaine série qui en trouvera une la remettra.
Scénario 6 · affamez-le de RAM
Les mêmes quatre tâches, ré-exécutées avec des budgets mémoire stricts de 2 GB, 1 GB et 256 MB : ce que le dimensionneur automatique choisirait sur une machine de 8 GB, une machine de 4 GB et un NAS de 2 GB. Chaque manche a produit un fichier correct, entièrement vérifié et extrait ; le pic de RSS a suivi le budget, pas la tâche. Temps jusqu’au fichier utilisable, ligne 10 GbE :
| Taille de tâche | RAM à volonté | budget 2 GB | budget 1 GB | budget 256 MB |
|---|---|---|---|---|
| 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 |
Le surcoût de 20–40% sur les grosses tâches est un artefact du 10 GbE : les blocs débordés ne coûtent du temps que lorsque la ligne dépasse le disque. La même tâche de 87 GB aux mêmes budgets sur une ligne ~2.4 Gbps a mesuré −1% à +7%, du bruit. Sur une connexion domestique typique, un petit budget est quasi gratuit quelle que soit la taille de la tâche. Un profil NAS (2 connexions, budget 256 MB) a fini la tâche de 35 GB avec un pic de RSS de 0.4 GB. Un NAS de 2 GB peut faire tourner ça. Aucun autre client n’offre le moindre plafond mémoire.
Scénario 7 · des archives dans des archives
Les posts arrivent de plus en plus souvent imbriqués : un RAR dans un RAR, un 7z niché dans une archive en mode store, un empilement de couches, une chaîne de mots de passe. Cette manche note ce qui reste à la charge de l’opérateur. auto signifie chaque charge utile extraite, identique à l’octet, sans la moindre intervention ; manuel signifie que le client a annoncé un succès mais a laissé une archive interne dans le dossier de sortie, à ouvrir vous-même.
| forme | nzbfast | SABnzbd | NZBGet | rustnzb |
|---|---|---|---|---|
| RAR en mode store dans un RAR en mode store | auto | auto | manuel | manuel |
| RAR compressé dans un RAR en mode store | auto | auto | manuel | manuel |
| 7z dans un RAR en mode store | auto | auto | manuel | manuel |
| empilement de 5 niveaux, 6 charges utiles | auto · 6/6 | manuel · 3/6 | manuel · 1/6 | manuel · 1/6 |
| chaîne de mots de passe, 3 niveaux chiffrés | auto · 3/3 | demande un mot de passe | demande un mot de passe | échec |
| complétion auto, les dix formes | 8/10 | 6/10 | 2/10 | 2/10 |
Banc en boucle locale, corpus généré par machine, les quatre clients sur la même machine, notation par hachage du contenu, si bien qu’un client qui renomme la charge utile garde son crédit. Comme les couches internes sont désimbriquées à la volée, nzbfast ne garde qu’une seule copie d’environ 1.5 GB sur disque là où les clients « écrire puis extraire » en gardent ~3 GB, et boucle ces manches en 1–2 s contre 4–8 s. Sur la chaîne de mots de passe, le mot de passe de chaque couche arrive dans un fichier que la couche au-dessus extrait : nzbfast le lit et déverrouille les trois niveaux ; les autres s’arrêtent et attendent que vous le tapiez. Les deux formes qu’il ne complète pas tout seul sont notées durement à dessein : un empilement de 10 niveaux au-delà de sa limite de profondeur par défaut et un post endommagé aux trois niveaux. Sur les deux, il récupère plus de charges utiles que n’importe quel autre client, mais sort avec un code non nul au lieu de qualifier de succès une tâche partielle, donc les deux comptent ici comme des échecs.
Duels de composants
L’extraction et le PAR2 sont notre propre code natif, alors nous les faisons aussi courir seuls contre le peloton sur des corpus identiques. Un temps ne compte que lorsque la sortie est identique à l’octet à la charge utile source.
Face à unrar 7.23, 7-Zip, bsdtar, unar et la crate rars amont sur un Apple M3 Ultra, l’extracteur de nzbfast gagne ou fait match nul sur chaque forme : 400 petits fichiers en 0.13 s contre 0.66 s pour unrar, solid 0.50 contre 0.87, chiffré 0.49 contre 0.82, une archive RAR7 à dictionnaire de 128 MB 0.71 contre 0.92. Relancé sur un M1 Ultra à 20 cœurs et sur un portable Intel à 14 cœurs, le résultat tient sur chaque forme, et sur le portable les marges s’élargissent : les chemins de décodage parallèles montent en charge sur les threads supplémentaires. Chaque temps rapporté a produit une sortie identique en sha256.
Face au par2cmdline classique, au fork SIMD par2cmdline-turbo et à MultiPar, nzbfast a la vérification la plus rapide et la réparation la plus rapide sur chaque machine testée. Bureau à 20 cœurs : vérification propre 0.40 s contre 1.08 pour turbo et 3.67 pour le classique ; réparation de 101 blocs endommagés 1.26 s contre 2.61 et 7.52. Portable à 14 cœurs : vérification 1.26 contre 1.48, réparation 2.57 contre 3.62. Chaque fichier réparé identique à l’octet. Une note honnête : nous ne créons pas de PAR2 (un téléchargeur n’en a pas besoin, et ParPar règne sur cette manche).
Ce qu’une tâche vous coûte
La promesse d’une seule passe concerne le disque autant que la vitesse ; la voici mesurée plutôt qu’affirmée : le maximum atteint par le répertoire de travail pendant les runs imbriqués, relevé deux fois par seconde. Une seule lecture à la fin ne voudrait rien dire, car un client qui supprime ses volumes après extraction semblerait ne jamais les avoir écrits.
| forme | nzbfast | NZBGet 26.2 | rustnzb 1.3.4 | SABnzbd 5.0.4 |
|---|---|---|---|---|
| RAR store dans un RAR store | 1538 | 1538 | 1774 | 3080 |
| couche interne compressée | 1536 | 1536 | 1674 | 3102 |
| RAR dans RAR, profondeur 2 | 1536 | 1536 | 1714 | 3076 |
| 7z enveloppé dans un RAR store | 1503 | 1536 | 1722 | 3102 |
En mégaoctets, plus bas est meilleur. NZBGet nous égale ici et il vaut la peine de dire pourquoi : il tourne avec DirectUnpack et DirectWrite activés, comme nous configurons chaque concurrent, et sur ces formes cela suffit à n’occuper qu’une copie sur le disque. SABnzbd en garde deux. L’écart qui subsiste est celui pour lequel le pipeline a été conçu : nous ne matérialisons jamais les volumes, donc le pic correspond à la charge utile elle-même et non à la charge plus l’archive qui la transportait.
Des capacités, pas des micro-benchmarks
| nzbfast | SABnzbd 5 | NZBGet 26 | rustnzb | Usenapp | Newsbin | |
|---|---|---|---|---|---|---|
| NNTP pipeliné | oui | désactivé par défaut | non | oui | - | - |
| vérification complète pendant le téléchargement | chaque bloc | après | quick-check | après | après | après |
| extraction pendant le téléchargement | au fil du flux, aucun volume sur disque | extraction directe⁴ | extraction directe⁴ | non fiable⁵ | non | non |
| disque requis pour un post de N GB | ~1×N | ~2×N | ~2×N | ~2×N | ~2×N | ~2×N |
| verdict de complétabilité avant téléchargement | au bloc près | non | % de santé | non | contrôle d’articles | non |
| mémoire bornée (jamais de swap) | budgétée | 9.3 GB @ 190 GB | réglage de cache | non | - | - |
| vérifier le fichier à n’importe quel point pendant le téléchargement | oui | non | non | non | séquentiel | non |
| indexeur intégré + mur d’affiches | oui, sans clé | non | non | non | interface de recherche | navigateur de groupes |
| intégration directe Sonarr/Radarr | API SAB + Newznab | natif | natif | partiel | non | non |
| télécommandes mobiles (nzb360/LunaSea) | via RPC NZBGet | oui | oui | non | non | non |
| récupération auto par liste de suivi + montées en qualité | intégrée | via *arr | via *arr | non | Watchdog | règles |
| binaire unique autonome | oui | Python | oui | oui | .app | .exe |
| open source | GPL⁶ | GPL | GPL | oui | payant | payant |
| plateformes | mac/win/linux/docker | mac/win/linux | mac/win/linux | linux/win | mac uniquement | win uniquement |
⁴ L’extraction directe matérialise quand même les volumes d’abord : 2× d’écritures et 2× de disque. ⁵ rustnzb a livré des volumes obfusqués marqués « Terminé » lors de notre manche (son extraction se bloque aussi avec l’unrar de RARLab si on ne la désactive pas). ⁶ GPL-3.0-or-later. Usenapp/Newsbin sont des lecteurs commerciaux mono-plateforme dotés de fonctions de téléchargement ; ils figurent ici parce qu’on nous pose la question, pas parce qu’ils rivalisent en vitesse.
Preuve de transport