Apollo Download ManagerApollo Download Manager
On this page

Torrent peer discovery, trackers and performance (#352)

Date: 2026-11-06. Question it answers: how the app's torrents find peers and how fast they download today, measured, and which changes are worth trying next.

This is research, not a decision. It changes no engine behaviour. Each proposed change is its own issue, to be measured before and after.

Code read at: 92d626b (main), with libtorrent-rasterbar 2.0.15. Measured with: the torrent helper built from that commit in release mode.

How facts are marked:

  • Code: read in this repository at that commit.

  • libtorrent: read in libtorrent 2.0.15's source (src/settings_pack.cpp at tag v2.0.15).

  • Measured: from the runs in part D.

  • Assumed: not checked; a reason to measure.

Short answer

  • Small torrents are fast and steady. Debian's 0.8 GB image finished in 88 to 95 s in all six runs, at 8.3 to 8.8 MiB/s.

  • Large ones are not. Ubuntu's 2.9 GB image took 323 and 346 s in two runs of six, and 764 to 1321 s in the other four, at both times of day.

  • The slow runs wait for peers at the start (#386): one peer for about 15 minutes, then the whole swarm at once. Why is #387's question.

  • Peers are found quickly. The first peer came within 0.5 to 5 s, and the metadata within 0.5 s, in all twelve runs.

  • Most of the engine runs on libtorrent's defaults. The app sets discovery, ports, limits and the proxy; choking, piece picking, uTP and the disk are libtorrent's choices.

  • One privacy bug was found and fixed: the Extra trackers setting reached private torrents (#377).

A. What the app sets today

From crates/velocity-torrent/src/engine.rs (session_config) and crates/velocity-lt/cpp/shim.cpp (code):

SettingThe app's valueNote
Listening0.0.0.0 and [::] on port 6890The user can change the port
DHTOnThrough a proxy, only with SOCKS5
Peer exchangeOnPer torrent; libtorrent turns it off for private torrents
Local peer discoveryOffOff through any proxy
Port mapping (UPnP, NAT-PMP)OffOne setting for both; off through any proxy
DHT bootstrap nodeslibtorrent's own unless the user sets somelibtorrent's default is dht.libtorrent.org:25401 (libtorrent)
Peers per torrent55max_connections per torrent
Global connectionsNot setlibtorrent's default, 200 (libtorrent)
Rate limitsThe user'sGlobal and per torrent
Queue (active_downloads, active_seeds, active_limit)-1, no limitThe app schedules torrents itself
ProxyHostnames, peers and trackers all through it
Extra trackersThe user's list, at most 64Added to every public torrent (#377)

Left to libtorrent 2.0.15 (libtorrent), with their defaults:

AreaDefault
Chokingfixed_slots_choker, 8 unchoke slots; seeding round_robin
uTP and TCPBoth on, incoming and outgoing; mixed mode peer_proportional
Connecting30 connection attempts a second, torrent_connect_boost 30, peer_connect_timeout 15 s
Peer timeoutspeer_timeout 120 s, inactivity_timeout 600 s, min_reconnect_time 60 s, max_failcount 3
Peer list3000 per torrent, 1000 while paused
Requestsrequest_queue_time 3 s, up to 500 outstanding, piece_timeout 20 s, request_timeout 60 s, strict_end_game_mode on
Turnoverpeer_turnover 4 % every 300 s, below 90 % of the limit
Disk10 I/O threads, 1 hashing thread, memory-mapped writes, the system's cache
Trackersannounce_to_all_trackers and announce_to_all_tiers off

After a restart: a torrent's own trackers come back with its resume data. The user's extra trackers are added again from the settings when the torrent is restored (code).

B. Public tracker lists

Some download managers add a long list of public trackers to every torrent, to find more peers. The options for the PO:

OptionWhat it meansCost
1. None (today)A torrent's own trackers, DHT and peer exchangeFewer peers for a poorly tracked torrent
2. The user's own list (today's Extra trackers)The user pastes a list they trustThe user has to find and maintain one
3. A list shipped with each releaseA list chosen and checked at release timeGoes stale between releases; the project vouches for those trackers
4. A list fetched and refreshed onlineThe app downloads a public list now and thenA network call beyond the downloads, which needs PO approval (AGENTS.md, "No telemetry"); the list's publisher decides what the app announces to

For every option:

  • Privacy: each extra tracker learns the user's address and the torrent's info hash. PRIVACY.md would have to say so.

  • Private torrents never get them. That rule is now enforced and tested (#377).

  • Dead trackers cost an announce each and are retried; libtorrent backs off after failures (libtorrent's tracker back-off, assumed, not measured here).

  • Legal: public trackers are used for all kinds of content. Whether the project should point users at any is for the PO and Singlbase.

Not measured: whether a public list finds more peers for the well-seeded torrents in part D. They already reached the 55-peer limit, so it likely wouldn't help there (assumed).

C. Performance and reliability

Each item is a hypothesis with a way to test it.

AreaWhat might helpHow to test
Long downloads slowing downFound by #386: at the start, waiting about 15 minutes for peersWhy, and how to get peers sooner (#387)
Peers per torrentAbove 55, if a torrent is limited by peersRuns at 55 and at 100 on the same torrent; every run here already reached 51 to 55 peers
Incoming connectionsPort mapping on, so peers behind other NATs can connect inRuns with port mapping on and off, counting incoming peers
Local peer discoveryPeers on the same networkOnly matters on a LAN with other clients; not worth measuring now
uTP and TCPlibtorrent's mixed mode defaults are tuned for being polite on a shared lineLeave as is unless a measurement points here
DiskMemory-mapped writes are libtorrent 2.0's defaultWatch the helper's memory and the disk queue in the time series
RecoveryAlready tested: a killed helper is restarted and its torrents carry on (crates/velocity-torrent/tests/lifecycle.rs)Field test R6 (tests/field/CHECKLIST.md)

D. Measurement

The method

crates/velocity-torrent/examples/torrent_baseline.rs, run by hand, never in CI:

cargo build --release -p velocity-torrent --bin velocity-torrent --example torrent_baseline
target/release/examples/torrent_baseline target/release/velocity-torrent <.torrent file> <work folder> <runs>
  • Each run starts fresh: a new helper with the app's default settings, in a new folder, so it remembers no peers or DHT nodes.

  • Only the port differs: 6891, so it can't clash with a running app.

  • What it reports: times to the metadata, the first peer and the first byte, and to completion; the mean speed from the first byte; the peak speed as the best 5 seconds, so one burst isn't called a speed; and the most peers and seeds seen.

  • It cleans up: each run's download is deleted.

  • Its sums are tested: cargo test --no-default-features -p velocity-torrent --example torrent_baseline.

The torrents

TorrentSizeFrom
Debian 13.7.0 netinst, amd640.79 GBcdimage.debian.org/debian-cd/current/amd64/bt-cd/
Ubuntu 26.04.1 live server, amd642.93 GBreleases.ubuntu.com/26.04.1/, the same file as the HTTP speed runs

The results, Windows 11, the PO's PC and connection

Set 1, 2026-11-06 from 20:01 (measured):

RunTorrentMetadataFirst peerFirst byteDoneMeanPeakPeers
1Debian0.5 s1.5 s4.5 s94 s8.43 MiB/s13.63 MiB/s51
2Debian0.5 s0.5 s3.5 s95 s8.29 MiB/s12.99 MiB/s55
3Debian0.5 s1.0 s7.5 s94 s8.78 MiB/s12.99 MiB/s55
1Ubuntu0.5 s2.0 s5.5 s1205 s2.33 MiB/s12.99 MiB/s55
2Ubuntu0.5 s5.0 s15.0 s1321 s2.14 MiB/s10.84 MiB/s55
3Ubuntu0.5 s1.5 s6.0 s323 s8.81 MiB/s13.72 MiB/s54

Set 2, 2026-11-06 from 23:11 (measured):

RunTorrentMetadataFirst peerFirst byteDoneMeanPeakPeers
1Debian0.5 s1.5 s3.5 s91 s8.67 MiB/s12.33 MiB/s54
2Debian0.5 s0.5 s2.5 s88 s8.83 MiB/s14.88 MiB/s46
3Debian0.5 s0.5 s3.0 s91 s8.62 MiB/s13.78 MiB/s54
1Ubuntu0.5 s2.0 s3.5 s346 s8.15 MiB/s12.63 MiB/s55
2Ubuntu0.5 s2.0 s28.6 s764 s3.80 MiB/s13.03 MiB/s52
3Ubuntu0.5 s2.0 s7.5 s1189 s2.36 MiB/s12.93 MiB/s55

Spread over both sets (measured): Debian 88 to 95 s, median 92 s. Ubuntu 323 to 1321 s, median 976 s; 2 of 6 runs near the direct-download time, 4 slow.

What the numbers say

  • Repeatable for Debian: all six runs within 7 s, at both times of day.

  • Not for Ubuntu: the fast runs match Debian's speed, and the slow ones reached the same peak. It happened at both times of day, so it isn't only the hour. While watching run 1, its download was at 2.79 of 2.93 GB and gaining about 0.6 MB/s, so at least part of the time went at the end. That is one observation, not a measurement.

  • Against direct downloads: single HTTP downloads of the same Ubuntu file took 286 s in V1 and 294 to 319 s in the app on this connection (2026-10-30, one run each). Ubuntu run 3, at 323 s, is close to that. The two slow runs are not.

Where the slow runs lose their time (#386, 2026-11-07)

The tool now saves every half-second sample (<work>/run-<n>.tsv), the slowest 30 seconds of each run, and the trackers' states (run-<n>-trackers.tsv). Five more Ubuntu runs, built from main at 8c7280e (measured):

RunStarted (about)DoneMeanSlowest 30 sPeers then
103:301177 s2.39 MiB/sfrom 155 s, 0.01 MiB/s, 0.3 % done1
203:501199 s2.36 MiB/sfrom 782 s, 0.00 MiB/s, 1.3 % done1
304:10459 s6.19 MiB/sfrom 210 s, 1.13 MiB/s, 41.8 % done3
404:23295 s9.60 MiB/sat the start, 8.20 MiB/s0
504:28311 s9.20 MiB/sfrom 281 s, 6.95 MiB/s, 92.5 % done0

What the samples show (measured):

  • The slow runs lose their time at the start, not the end. Runs 1 and 2 had one peer, not a seed, for 900 s, and gained about 2 MB a minute: 33.8 and 40.3 MiB done at 900.6 s.

  • Then the swarm arrives at once. By 910.6 s they had 16 to 20 peers, by 930 s over 30, and the rest of the file took about 4 minutes at full speed.

  • Run 3 waited too, for less: 2 to 5 peers for its first 6 minutes, then 48 by 420 s.

  • The fast runs had 27 to 32 peers within 30 s.

  • The trackers, in the fast runs: torrent.ubuntu.com answered over IPv4 within 1.5 s, reporting about 1,120 seeds. The IPv6 tracker always failed ("unreachable"): this connection has no working IPv6.

  • Not yet captured: the trackers' answers in a slow run. The tracker log was added after runs 1 to 3.

The lead (assumed, not proven): 900 s is libtorrent's dht_announce_interval (part A). A run whose first announce gives it almost no peers waits for the next DHT round. Why the tracker gave so few in those runs is what #387 has to find, with the tracker log now in place.

E. The plan

In the order recommended, each its own issue. Which release each goes in is the PO's choice.

IssueChangeExpected benefitRiskSizeHow it's measured
#386The measuring tool records a time series, the slowest stretch and the trackersShowed the slow runs wait about 15 minutes for peers at the startNone: a tool onlySmallDone: see "Where the slow runs lose their time"
#387Then, from #386's finding: why the first announce gives so few peers, and what gets them sooner (for example the DHT's first announce, or announcing to every tracker)Long downloads as steady as short onesMedium: libtorrent settings change for everyoneMediumUbuntu runs before and after, at least 3 each, at two times of day
#384Port mapping: decide its default (PO)More peers can connect inOpens a port on the routerSmallIncoming peer counts with it on and off
#385Public tracker list: decide among part B's options (PO)More peers for poorly tracked torrentsPrivacy, legalDepends on the optionPeers found on a poorly tracked torrent with and without
#388Linux: repeat the method thereShows whether the slow stretch is the same on LinuxNoneSmallThe same tool

Not proposed: changing the peer limit, uTP or the disk settings. Nothing measured points there yet.