Skip to content

feat(stats): measure the download rate from received bytes, not verified pieces - #35

Merged
daniboybye merged 1 commit into
masterfrom
feat/byte-granular-rate
Oct 25, 2026
Merged

daniboybye merged 1 commit into
masterfrom
feat/byte-granular-rate

Conversation

@daniboybye

Copy link
Copy Markdown
Owner

Requested by Daniel Urumov

Before: the download rate was derived from the verified-piece counter, so with 1 MiB pieces a 64 KB/s torrent read anywhere from 12 to 157 KB/s and a torrent slower than one piece per window read 0 while bytes were arriving. The connection manager's "low speed" gate accepted only integers while the rate is a float in bytes/ms, so every downloading torrent counted as slow at any speed: discovery escalated below 50 peers and the snub path ran above 12.

After: the rate is the payload actually received, differenced over a 20 s sliding window, and the gate compares bytes per second against its 32 KiB/s threshold.

How: a new Torrent.ReceivedBytes (a public write_concurrency ETS table owned by an app-level process) is bumped with :ets.update_counter/4 for every accepted block in Peer.Controller.State.count_block/2; Torrent.Model.download_rate/1 differences it over its 5 s samples; Torrents.remove/2 drops the row; ConnectionManager.low_download_speed?/1 accepts any number and converts units. Live: two torrents downloaded on this build with the counter ending at 100.9% and 102.6% of their sizes (endgame duplicates), completed torrents read 0.0, no errors. New tests fail on the old code. All twelve locally reproducible CI gates pass (1880 tests); Trivy, the Codecov upload and the SARIF upload run only in CI.

🤖 Generated with Claude Code

…ied pieces

The download readout differenced Torrent.Model.downloaded, which moves
only when a whole piece completes and verifies. With 1 MiB pieces a
64 KB/s torrent read anywhere from 12 to 157 KB/s, and one slower than a
piece per window read 0 while bytes were arriving.

Each Peer.Controller now adds every accepted block to a per-torrent
counter (Torrent.ReceivedBytes, an atomic ETS update_counter, no
messages), and the Model differences that counter over a 20 s sliding
window. A live run of two torrents ended with the counter at 100.9% and
102.6% of their sizes, the excess being endgame duplicates.

The same number gates Peer.ConnectionManager, whose check accepted only
integers while the Model reports a float in bytes per millisecond, so
every downloading torrent counted as slow: discovery escalated below 50
peers and the snub path ran above 12 at any speed. It now compares
bytes per second against the 32 KiB/s threshold.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@daniboybye daniboybye self-assigned this Oct 25, 2026
@codecov

codecov Bot commented Oct 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.66667% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
lib/elixir_torrent/torrent/received_bytes.ex 78.57% 3 Missing ⚠️
lib/elixir_torrent/peer/connection_manager.ex 50.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@daniboybye
daniboybye merged commit f06caac into master Oct 25, 2026
4 checks passed
@daniboybye
daniboybye deleted the feat/byte-granular-rate branch October 30, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant