Method
How the race is run
Everything needed to check a number on these pages: what one run is, how a run is won, what each number measures, and the files they come from.
One run
- A fresh 1 GiB torrent of random bytes in 1 MiB pieces, flagged private, made for that run.
- 2 seeders, qBittorrent 5.1.0, with their upload slots opened and no rate cap.
- A local HTTP tracker (BEP 3) with one passkey per client, as a private tracker issues. It answers “unregistered” until the setup's tracker lag has passed, then accepts.
- The four racing clients are added in the same second. The race lasts 60 s.
- Each client is asked for its state every 10 ms until its first verified piece and every 100 ms after.
- Every finished copy is checked against the original with SHA-256, and what each client reported uploading is checked against the tracker's own count.
The four setups
| Setup | Disk | Tracker lag | Legs | Runs |
|---|---|---|---|---|
| SSD · no lag | C: CT500P5PSSD8 (SSD) | 0 s | stock-t0 | 5 |
| SSD · 5 s lag | C: CT500P5PSSD8 (SSD) | 5 s | stock-t5 | 5 |
| HDD · no lag | H: ST18000NM000J-2TV103 (HDD) | 0 s | spindle-t0, spindle-t0b | 8 |
| HDD · 5 s lag | H: ST18000NM000J-2TV103 (HDD) | 5 s | spindle-t5 | 4 |
A leg is one session of runs; a setup's second leg is the same scenario on another night and pools into it.
How a run is won
- Each run, rbittorrent is held against the best of the other three clients in that run, on four marks: registered first (the tracker's first accepting answer, counted from the race start), finished first, uploaded the most in the first 60 s, and uploaded the most by the end.
- Finished means every piece in and checked against its hash. On a spinning disk the last write can land a little later; it lands about when the fastest rival's does.
- A tie is not a win. A client that never registered or never finished loses that mark.
- The rule is the bench's own
scorecard_marks.py, which these pages import rather than copy.
What each number is
- Tracker's first answer, from the race start: what the marks use; it includes the order the clients were added in.
- Tracker's first answer, from its own fetch: from the moment each client fetched the torrent file to its first accepting answer, like for like.
- Every piece in and hash-checked: from the race start to the client reporting every piece verified.
- Upload share: what one racing client sent the other racing clients, of everything they sent each other; the seeders' upload is not counted.
- Every number is a median over the setup's runs, with the fastest and slowest run beside it.
Time until every piece was in and hash-checked (lower is better)
The numbers as a table
| Client | SSD · T=0 s | SSD · T=5 s | HDD · T=0 s | HDD · T=5 s |
|---|---|---|---|---|
| rbittorrent | 1.31 s (0.89 to 1.37 s) | 8.12 s (7.82 to 13 s) | 29.5 s (22.7 to 33.1 s) | 14.3 s (12.1 to 15.8 s) |
| rTorrent | 3.11 s (2.24 to 3.53 s) | 17.1 s (16.5 to 17.7 s) | 41.3 s (26.6 to 47.3 s), 4 of 8 runs | 26.4 s (19.2 to 33.9 s) |
| qBittorrent | 6.73 s (6.5 to 8.31 s) | - | 34.2 s (27.9 to 41.1 s) | - |
| Deluge | 13.5 s, 1 of 5 runs | - | - | - |
Median (fastest to slowest run), and how many runs produced a number when not all did. "-": none did.
Share of the racers' upload in the first 60 s (higher is better)
The numbers as a table
| Client | SSD · T=0 s | SSD · T=5 s | HDD · T=0 s | HDD · T=5 s |
|---|---|---|---|---|
| rbittorrent | 69% (59 to 73%) | 100% | 67% (57 to 72%) | 100% |
| qBittorrent | 6.1% (3.3 to 20%) | 0% | 24% (19 to 28%) | 0% |
| rTorrent | 22% (15 to 29%) | 0% | 6.8% (4.8 to 11%) | 0% |
| Deluge | 1.7% (0.3 to 4%) | 0% | 4.1% (0 to 7.2%) | 0% |
Median (fastest to slowest run), and how many runs produced a number when not all did. "-": none did.
Machine and versions
One 1,024 MiB private torrent; 2 seeders (qBittorrent 5.1.0 with its upload slots opened, no rate cap); 4 clients added in the same second; a 60 s race. Runs per setup: SSD · T=0 s 5, SSD · T=5 s 5, HDD · T=0 s 8, HDD · T=5 s 4. Bench PC: 12th Gen Intel(R) Core(TM) i7-12700K, 16 GB, Microsoft Windows 10 Pro (build 19045); SSD CT500P5PSSD8 (NVMe), HDD ST18000NM000J-2TV103 (SATA). Versions: rbittorrent 5c0a4427 on rlibtorrent ca2067a4, qBittorrent 5.1.0, Deluge 2.2.0, rTorrent 0.9.8 (WSL 2, Ubuntu). Scorecard 208, 2026-10-18.
Every number, every setup
SSD, tracker lag 0 s, 5 runs
| rbittorrent | rTorrent | qBittorrent | Deluge | |
|---|---|---|---|---|
| Tracker's first answer, from the race start | 6.9 ms (4.9 to 11.6 ms) | 9.6 ms (7.4 to 13.5 ms) | 1.21 s (0.97 to 1.21 s) | 501 ms (25.1 to 519 ms) |
| First verified piece | 23 ms (20 to 36 ms) | 41 ms (36 to 67 ms) | 2.17 s (1.95 to 2.19 s) | 516 ms (55 to 532 ms) |
| Every piece in and hash-checked | 1.31 s (0.89 to 1.37 s) | 3.11 s (2.24 to 3.53 s) | 6.73 s (6.5 to 8.31 s) | 13.5 s, 1 of 5 runs |
| Upload share at 60 s | 69% (59 to 73%) | 22% (15 to 29%) | 6.1% (3.3 to 20%) | 1.7% (0.3 to 4%) |
| Copies that failed SHA-256, of those checked; uploads the tracker counted differently | 0 of 5; 0 | 0 of 5; 0 | 0 of 5; 0 | 0 of 1; 0 |
SSD, tracker lag 5 s, 5 runs
| rbittorrent | rTorrent | qBittorrent | Deluge | |
|---|---|---|---|---|
| Tracker's first answer, from the race start | 7.02 s (7.01 to 7.03 s) | 14.6 s (14.4 to 14.8 s) | - | - |
| Tracker's first answer, from its own fetch | 7.02 s (7.01 to 7.03 s) | 14.6 s (14.3 to 14.8 s) | - | - |
| First verified piece | 7.05 s (7.04 to 7.08 s) | 14.8 s (14.4 to 15 s) | - | - |
| Every piece in and hash-checked | 8.12 s (7.82 to 13 s) | 17.1 s (16.5 to 17.7 s) | - | - |
| Upload share at 60 s | 100% | 0% | 0% | 0% |
| Copies that failed SHA-256, of those checked; uploads the tracker counted differently | 0 of 5; 0 | 0 of 5; 0 | 0 of 0; 0 | 0 of 0; 0 |
HDD, tracker lag 0 s, 8 runs
| rbittorrent | qBittorrent | rTorrent | Deluge | |
|---|---|---|---|---|
| Tracker's first answer, from the race start | 6.4 ms (4.7 to 20.8 ms) | 1.02 s (0.86 to 1.18 s) | 7.7 ms (7.3 to 29.8 ms) | 483 ms (426 to 505 ms), 7 of 8 runs |
| Tracker's first answer, from its own fetch | 2.3 ms (1.2 to 16.2 ms) | 1.02 s (0.86 to 1.17 s) | 2.4 ms (1.9 to 2.8 ms) | 477 ms (418 to 499 ms), 7 of 8 runs |
| First verified piece | 106 ms (67 to 137 ms) | 2.01 s (1.85 to 2.2 s) | 149 ms (83 to 227 ms) | 590 ms (535 to 670 ms), 7 of 8 runs |
| Every piece in and hash-checked | 29.5 s (22.7 to 33.1 s) | 34.2 s (27.9 to 41.1 s) | 41.3 s (26.6 to 47.3 s), 4 of 8 runs | - |
| Upload share at 60 s | 67% (57 to 72%) | 24% (19 to 28%) | 6.8% (4.8 to 11%) | 4.1% (0 to 7.2%) |
| Copies that failed SHA-256, of those checked; uploads the tracker counted differently | 0 of 8; 0 | 0 of 8; 0 | 0 of 4; 0 | 0 of 0; 1 |
HDD, tracker lag 5 s, 4 runs
| rbittorrent | rTorrent | qBittorrent | Deluge | |
|---|---|---|---|---|
| Tracker's first answer, from the race start | 7.03 s (7.03 to 7.03 s) | 14.4 s (14.3 to 15 s) | - | - |
| Tracker's first answer, from its own fetch | 7.02 s (7.02 to 7.03 s) | 14.4 s (14.3 to 15 s) | - | - |
| First verified piece | 7.15 s (7.08 to 7.16 s) | 14.7 s (14.5 to 15.3 s) | - | - |
| Every piece in and hash-checked | 14.3 s (12.1 to 15.8 s) | 26.4 s (19.2 to 33.9 s) | - | - |
| Upload share at 60 s | 100% | 0% | 0% | 0% |
| Copies that failed SHA-256, of those checked; uploads the tracker counted differently | 0 of 4; 0 | 0 of 4; 0 | 0 of 0; 0 | 0 of 0; 0 |
Runs left out
On a spinning disk the seeders must read the test file off that disk. A run whose seeders read under half of it was served from the file cache, so it measures memory rather than the disk, and is left out. A run since the harness evicts the file says so in its own result file.
spindle-t0/stock-T0-run2: its uploaders read 0.07 GiB of the 1 GiB fixture off H:: the fixture was still in the file cache.spindle-t0b/stock-T0-run2: its uploaders read 0.34 GiB of the 1 GiB fixture off H:: the fixture was still in the file cache.spindle-t5/stock-T5-run2: its uploaders read 0.00 GiB of the 1 GiB fixture off H:: the fixture was still in the file cache.
What these numbers do not cover
- One machine: 12th Gen Intel(R) Core(TM) i7-12700K, 16 GB, Microsoft Windows 10 Pro. Another machine, disk or network can order the clients differently.
- One torrent size in the race (1 GiB), and seeders on the same machine rather than a public swarm over the internet.
- Transmission and uTorrent are not in the race.
- rTorrent runs inside WSL, where the sampler cannot see its memory.
The files
The whole scorecard as these pages read it: scorecard.json. Each leg's own summary, as the bench wrote it:
Source folder: bench/results/2026-10-18-p5c0a4427eca2067a4-scorecard-card208-race in the bench repository, harness bench/harness/race_scenario.py.
Terms used here
- Tracker
- The server that tells each client which other clients have the torrent. A client “announces” to it to join.
- Announce
- A client's request to the tracker: here I am, who else has this torrent?
- Registered (Announce OK)
- The tracker's first answer that accepts the client. Until then the client gets no peers from it.
- Private torrent
- A torrent flagged so that clients find peers only through its tracker: no DHT, no peer exchange, no local discovery. Private trackers depend on it to count every byte.
- Tracker lag (T)
- How long the race's tracker answers “unregistered” after the start, as a private tracker does while a new upload is still being processed. T=0 s: it accepts at once.
- Seeder
- A client that has the whole torrent and only uploads.
- Swarm
- Every client sharing one torrent at that moment.
- Piece
- The torrent's unit of data (1 MiB here). Each one is checked against its hash before it counts, so a client never shares a broken piece.
- What one racing client sent the other racing clients, as a share of everything they sent each other. The seeders' upload is not counted.
- Median and range
- The middle run, and the fastest and slowest. A median is not moved by one odd run; the range shows how much the runs differ.
- Peak private memory
- The most memory the client's process held for itself at any moment of the run.
- CPU time
- Processor time the client used, in seconds of one core.
- Info hash
- The hash that names a torrent; two clients mean the same torrent when it matches.
- DHT
- The distributed table clients use to find peers without a tracker (BEP 5).
- Peer exchange (PEX)
- Clients telling each other about further peers.
- uTP
- BitTorrent over UDP, with LEDBAT congestion control so it yields to other traffic.
- Oracle
- An independent implementation the engine's behaviour is compared against, here libtorrent, rqbit and Transmission.
- Fuzz target
- A test that feeds a parser endless generated input, looking for a crash or a hang.