chore: initial sanitized public snapshot
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
# Performance Evidence
|
||||
|
||||
Performance evidence starts here. This directory records benchmark design notes and measured results.
|
||||
|
||||
As of the Phase 3 Cargo-native workflow push, the canonical report-refresh
|
||||
entrypoint is:
|
||||
|
||||
```powershell
|
||||
rtk cargo run --manifest-path .\xtask\Cargo.toml -- perf collect-local-comparison
|
||||
```
|
||||
|
||||
`scripts/perf/collect_local_comparison.ps1` remains available as a thin
|
||||
compatibility shim for existing local workflows.
|
||||
|
||||
Current active performance evidence files:
|
||||
|
||||
- `optimization-ranking.md`
|
||||
- `rpc-pressure-evidence.md`
|
||||
- `criterion-benchmarks.md`
|
||||
- `local-comparison.md`
|
||||
- `size-evidence.md`
|
||||
@@ -0,0 +1,178 @@
|
||||
# Criterion Benchmarks
|
||||
|
||||
This file records the Criterion-backed benchmark suite for
|
||||
`aria2-rust-pro`.
|
||||
|
||||
## Purpose
|
||||
|
||||
This project needs a repeatable benchmark surface in addition to assertion-style
|
||||
regression tests. This suite converts the existing synthetic BT/RPC pressure
|
||||
patterns into Criterion benchmarks so later tranches can compare revisions and
|
||||
resource-limit tuning with the same workload shape.
|
||||
|
||||
## Bench Target
|
||||
|
||||
- crate: `crates/aria2-rust-pro-tests`
|
||||
- bench: `rpc_pressure`
|
||||
|
||||
## Current Coverage
|
||||
|
||||
The current suite measures nine deterministic scenarios:
|
||||
|
||||
1. `rpc_tell_status_pressure`
|
||||
- 64-task and 128-task BT-like dispatcher loads
|
||||
- repeated `aria2.tellStatus` calls under runtime tick churn
|
||||
2. `rpc_mixed_pressure`
|
||||
- 96-task and 192-task BT-like dispatcher loads
|
||||
- mixed `aria2.tellStatus`, `aria2.tellActive`, and `aria2.tellGlobalStat`
|
||||
batches
|
||||
3. `runtime_snapshot_pressure`
|
||||
- 64 / 128 / 256 download in-memory engine setups
|
||||
- repeated scheduler runs plus `runtime_instrumentation_snapshot()` capture
|
||||
4. `rpc_speed_limit_pressure`
|
||||
- 32-task and 64-task BT-like dispatcher loads
|
||||
- active `changeGlobalOption` / `changeOption` speed caps
|
||||
- repeated `tellStatus` plus `tellGlobalStat` under clamped runtime speeds
|
||||
5. `scheduler_backpressure_pressure`
|
||||
- 64-task and 128-task in-memory engine setups
|
||||
- mixed active/waiting/error groups
|
||||
- repeated scheduler runs plus runtime instrumentation under differing
|
||||
`disk-cache` budgets
|
||||
6. `live_http_transfer_contention_pressure`
|
||||
- loopback live HTTP transfer via `ReqwestHttpConnector` and
|
||||
`ConnectorBackedDownloader`
|
||||
- 16 KiB segmented HTTP downloads that force bootstrap `206` plus follow-up
|
||||
range requests
|
||||
- comparison between a loose-cap runtime and a tight
|
||||
`max-overall-download-limit` runtime so execution-layer throttling is
|
||||
measured instead of only inferred from RPC snapshots
|
||||
7. `live_http_multi_download_contention_pressure`
|
||||
- three concurrent loopback live HTTP downloads
|
||||
- each download still uses the existing CLI/runtime wiring, but all three
|
||||
contend against one local segment server at once
|
||||
- compares loose-cap vs tight-cap runtime configuration under aggregate
|
||||
multi-download contention
|
||||
8. `rpc_shared_runtime_fairness_pressure`
|
||||
- three-way and four-way BT-like dispatcher loads inside one runtime
|
||||
- one constrained gid completes, then the remaining active gids are expected
|
||||
to inherit a larger share of the global speed cap
|
||||
- verifies same-runtime cross-download rebalancing rather than only
|
||||
per-download segment throttling or separate parallel invocations
|
||||
9. `live_http_shared_runtime_multi_download_pressure`
|
||||
- three loopback live HTTP downloads registered into one invocation/runtime
|
||||
- uses the shared CLI runtime path rather than separate parallel invocations
|
||||
- compares loose-cap vs tight-cap runtime configuration for same-runtime live
|
||||
transfer behavior
|
||||
- now also includes a six-download `tight_cap_6way` variant so shared-runtime
|
||||
cap behavior is measured beyond the original 3-download / 16 KiB shape
|
||||
- now also includes `cache_pressure_6way_256k`, which raises per-download
|
||||
transfer size while constraining `disk-cache` so shared-runtime cache
|
||||
pressure is represented in the same benchmark family
|
||||
|
||||
## Commands
|
||||
|
||||
Canonical local report refresh:
|
||||
|
||||
```powershell
|
||||
rtk cargo run --manifest-path .\xtask\Cargo.toml -- perf collect-local-comparison
|
||||
pwsh ./scripts/perf/collect_local_comparison.ps1
|
||||
```
|
||||
|
||||
Compile-only verification:
|
||||
|
||||
```powershell
|
||||
rtk cargo bench --manifest-path .\Cargo.toml -p aria2-rust-pro-tests --bench rpc_pressure --no-run
|
||||
```
|
||||
|
||||
Short local run:
|
||||
|
||||
```powershell
|
||||
rtk cargo bench --manifest-path .\Cargo.toml -p aria2-rust-pro-tests --bench rpc_pressure -- --sample-size 10 --measurement-time 0.05 --warm-up-time 0.05
|
||||
```
|
||||
|
||||
## First Short Run Snapshot
|
||||
|
||||
Short local run on this workspace produced the following indicative timings:
|
||||
|
||||
- `rpc_tell_status_pressure/tell_status/64`
|
||||
- `1.3318 ms .. 1.3459 ms`
|
||||
- throughput `190.21 Kelem/s .. 192.22 Kelem/s`
|
||||
- `rpc_tell_status_pressure/tell_status/128`
|
||||
- `2.8581 ms .. 2.8726 ms`
|
||||
- throughput `178.24 Kelem/s .. 179.14 Kelem/s`
|
||||
- `rpc_mixed_pressure/mixed_rpc/96`
|
||||
- `59.918 us .. 64.561 us`
|
||||
- throughput `278.81 Kelem/s .. 300.41 Kelem/s`
|
||||
- `rpc_mixed_pressure/mixed_rpc/192`
|
||||
- `78.663 us .. 83.252 us`
|
||||
- throughput `216.21 Kelem/s .. 228.82 Kelem/s`
|
||||
- `runtime_snapshot_pressure/runtime_snapshot/64`
|
||||
- `8.3619 us .. 9.0689 us`
|
||||
- `runtime_snapshot_pressure/runtime_snapshot/128`
|
||||
- `15.452 us .. 17.835 us`
|
||||
- `runtime_snapshot_pressure/runtime_snapshot/256`
|
||||
- `31.072 us .. 33.087 us`
|
||||
- `rpc_speed_limit_pressure/speed_limit/32`
|
||||
- `64.896 us .. 66.191 us`
|
||||
- throughput `181.29 Kelem/s .. 184.91 Kelem/s`
|
||||
- `rpc_speed_limit_pressure/speed_limit/64`
|
||||
- `90.733 us .. 93.649 us`
|
||||
- throughput `128.14 Kelem/s .. 132.26 Kelem/s`
|
||||
- `scheduler_backpressure_pressure/backpressure/64`
|
||||
- `10.917 us .. 12.478 us`
|
||||
- throughput `5.1290 Melem/s .. 5.8625 Melem/s`
|
||||
- `scheduler_backpressure_pressure/backpressure/128`
|
||||
- `19.792 us .. 21.039 us`
|
||||
- throughput `6.0839 Melem/s .. 6.4673 Melem/s`
|
||||
- `live_http_transfer_contention_pressure/live_http_transfer/loose_cap`
|
||||
- `38.640 ms .. 39.143 ms`
|
||||
- throughput `408.76 KiB/s .. 414.07 KiB/s`
|
||||
- `live_http_transfer_contention_pressure/live_http_transfer/tight_cap`
|
||||
- `41.793 ms .. 48.988 ms`
|
||||
- throughput `326.61 KiB/s .. 382.83 KiB/s`
|
||||
|
||||
These are not cross-machine release numbers. They are the first local benchmark
|
||||
local benchmark anchor so later tuning and regressions can be compared against a
|
||||
stable local benchmark driver. The new live HTTP group is still loopback-local rather
|
||||
than internet-realistic, but it now exercises the segmented execution path with
|
||||
real socket I/O instead of only scheduler-facing synthetic churn.
|
||||
|
||||
- `live_http_multi_download_contention_pressure/multi_live_http_transfer/loose_cap`
|
||||
- `105.63 ms .. 106.46 ms`
|
||||
- throughput `450.86 KiB/s .. 454.43 KiB/s`
|
||||
- `live_http_multi_download_contention_pressure/multi_live_http_transfer/tight_cap`
|
||||
- `105.13 ms .. 105.52 ms`
|
||||
- throughput `454.90 KiB/s .. 456.56 KiB/s`
|
||||
- `rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/three_way_rebalance`
|
||||
- `70.687 us .. 72.082 us`
|
||||
- throughput `166.48 Kelem/s .. 169.76 Kelem/s`
|
||||
- `rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/four_way_rebalance`
|
||||
- `95.853 us .. 96.893 us`
|
||||
- throughput `165.13 Kelem/s .. 166.92 Kelem/s`
|
||||
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/loose_cap`
|
||||
- `107.57 ms .. 108.23 ms`
|
||||
- throughput `443.49 KiB/s .. 446.23 KiB/s`
|
||||
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap`
|
||||
- `118.77 ms .. 120.35 ms`
|
||||
- throughput `398.83 KiB/s .. 404.14 KiB/s`
|
||||
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap_6way`
|
||||
- `234.36 ms .. 236.30 ms`
|
||||
- throughput `406.26 KiB/s .. 409.63 KiB/s`
|
||||
- `live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/cache_pressure_6way_256k`
|
||||
- `96.98 ms .. 99.12 ms`
|
||||
- throughput `15.133 MiB/s .. 15.466 MiB/s`
|
||||
|
||||
## Intended Next Extension
|
||||
|
||||
This suite now mixes synthetic pressure and local loopback transfer. The next
|
||||
tranche should attach:
|
||||
|
||||
- comparisons against the upstream [aria2](https://github.com/aria2/aria2)
|
||||
reference and the [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core)
|
||||
reference baseline
|
||||
- further larger or more realistic same-runtime live transfer workloads beyond
|
||||
the new 6-download tight-cap and cache-pressure anchors
|
||||
- stronger disk-cache and backpressure scenarios with larger transfer/runtime
|
||||
contention
|
||||
- upstream aria2 / Aria2-Pro-Core reference-baseline comparison notes
|
||||
- memory and file-descriptor measurements recorded beside benchmark output
|
||||
@@ -0,0 +1,89 @@
|
||||
# Local Comparison
|
||||
|
||||
Generated: 2026-05-28 12:08:14 +00:00
|
||||
|
||||
## Environment
|
||||
|
||||
- Repo root: <repo-root>
|
||||
- Bench executable: <repo-root>\target\release\deps\rpc_pressure-386f010a5bd10aaf.exe
|
||||
- Manifest: <repo-root>\Cargo.toml
|
||||
- Bench process exit code: unavailable in this refresh
|
||||
- Peak working set during local bench run: unavailable in this refresh
|
||||
- Peak handle count during local bench run: unavailable in this refresh
|
||||
|
||||
## Reference Artifact Detection
|
||||
|
||||
- Reference projects: [Aria2-Pro-Core](https://github.com/P3TERX/Aria2-Pro-Core)
|
||||
and [aria2](https://github.com/aria2/aria2)
|
||||
- Rust CLI local executable: <repo-root>\target\release\aria2-rust-pro.exe
|
||||
- Original aria2 local executable: <repo-root>\dist\upstream\aria2-1.37.0-win-64bit-build1\aria2-1.37.0-win-64bit-build1\aria2c.exe
|
||||
- Original aria2 version summary: aria2 version 1.37.0; Enabled Features: Async DNS, BitTorrent, Firefox3 Cookie, GZip, HTTPS, Message Digest, Metalink, XML-RPC, SFTP; Compiler: mingw-w64 8.0.0 (alpha) / gcc 10-win32 20220113; built by x86_64-pc-linux-gnu; targeting x86_64-w64-mingw32; on Nov 15 2023 11:17:49
|
||||
- Aria2-Pro-Core reference executable: <aria2-baseline>\build\pro-core\windows-x64-mingw-30403\stage\aria2-pro-core-1.37.0+pro.20260523-windows-x64-mingw\aria2c.exe
|
||||
- Aria2-Pro-Core reference version summary: aria2 version 1.37.0; Enabled Features: Async DNS, BitTorrent, Firefox3 Cookie, GZip, HTTPS, Message Digest, Metalink, XML-RPC, SFTP; Compiler: mingw-w64 15.0.0 (alpha) / gcc 16.1.0; built by x86_64-w64-mingw32; on May 23 2026 15:48:03; Pro Build: 1.37.0+pro.20260523; Pro Commit: 64365cf3cdca441ab710d53be8e4ded37a9b3d7e
|
||||
- Comparison status: Rust local benchmarks and expanded same-host loopback HTTP comparisons were executed across Rust, the Aria2-Pro-Core reference baseline, and upstream aria2 on this Windows host.
|
||||
|
||||
## Same-Host Local HTTP Transfer Comparisons
|
||||
|
||||
- Payload bytes: 8388608
|
||||
- Payload SHA256: BDF23837181F5808331800C1AE2B4F7D7A839536B10D58491471C50DDE23833A
|
||||
|
||||
### single_file_split1
|
||||
|
||||
- One loopback HTTP file with split=1 and max-connection-per-server=1
|
||||
|
||||
| Binary | Exit code | Samples | Median | Spread | Output count | Output bytes | SHA256 all match |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| Rust CLI | 0 | 5 | 132.53 ms | 120.16 .. 138.76 ms | 1 | 8388608 | true |
|
||||
| Pro Core | 0 | 5 | 199.34 ms | 89.93 .. 211.04 ms | 1 | 8388608 | true |
|
||||
| Upstream aria2 | 0 | 5 | 181.67 ms | 172.38 .. 202.26 ms | 1 | 8388608 | true |
|
||||
|
||||
### segmented_single_file
|
||||
|
||||
- One loopback HTTP file with split=4 and max-connection-per-server=4
|
||||
|
||||
| Binary | Exit code | Samples | Median | Spread | Output count | Output bytes | SHA256 all match |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| Rust CLI | 0 | 5 | 125.49 ms | 121.33 .. 132.76 ms | 1 | 8388608 | true |
|
||||
| Pro Core | 0 | 5 | 209.49 ms | 208.44 .. 1197.45 ms | 1 | 8388608 | true |
|
||||
| Upstream aria2 | 0 | 5 | 174.51 ms | 171.90 .. 194.46 ms | 1 | 8388608 | true |
|
||||
|
||||
|
||||
## Rust Criterion Summary
|
||||
|
||||
| Benchmark | Mean | 95% CI |
|
||||
| --- | --- | --- |
|
||||
| bt_visibility_pressure/bt_visibility/32 | 910.409 us | 905.654 us .. 915.190 us |
|
||||
| bt_visibility_pressure/bt_visibility/64 | 1.8430 ms | 1.8378 ms .. 1.8490 ms |
|
||||
| live_http_multi_download_contention_pressure/multi_live_http_transfer/loose_cap | 11.6320 ms | 11.5494 ms .. 11.7368 ms |
|
||||
| live_http_multi_download_contention_pressure/multi_live_http_transfer/tight_cap | 11.5679 ms | 11.5103 ms .. 11.6136 ms |
|
||||
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/cache_pressure_6way_256k | 7.2873 ms | 7.1368 ms .. 7.4519 ms |
|
||||
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/loose_cap | 11.8141 ms | 11.6959 ms .. 11.9347 ms |
|
||||
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap | 11.8461 ms | 11.7319 ms .. 11.9568 ms |
|
||||
| live_http_shared_runtime_multi_download_pressure/shared_runtime_live_http_transfer/tight_cap_6way | 12.7498 ms | 12.6485 ms .. 12.8552 ms |
|
||||
| live_http_transfer_contention_pressure/live_http_transfer/loose_cap | 11.6614 ms | 11.4932 ms .. 11.8646 ms |
|
||||
| live_http_transfer_contention_pressure/live_http_transfer/tight_cap | 10.9603 ms | 10.8586 ms .. 11.0562 ms |
|
||||
| rpc_mixed_pressure/mixed_rpc/192 | 135.092 us | 134.021 us .. 136.230 us |
|
||||
| rpc_mixed_pressure/mixed_rpc/96 | 84.114 us | 82.923 us .. 85.222 us |
|
||||
| rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/four_way_rebalance | 88.653 us | 87.023 us .. 90.329 us |
|
||||
| rpc_shared_runtime_fairness_pressure/shared_runtime_fairness/three_way_rebalance | 66.833 us | 65.539 us .. 68.357 us |
|
||||
| rpc_speed_limit_pressure/speed_limit/32 | 60.370 us | 59.997 us .. 60.762 us |
|
||||
| rpc_speed_limit_pressure/speed_limit/64 | 90.078 us | 87.568 us .. 93.803 us |
|
||||
| rpc_tell_status_pressure/tell_status/128 | 2.6805 ms | 2.6576 ms .. 2.7154 ms |
|
||||
| rpc_tell_status_pressure/tell_status/64 | 1.3265 ms | 1.3112 ms .. 1.3412 ms |
|
||||
| runtime_snapshot_pressure/runtime_snapshot/128 | 24.534 us | 23.895 us .. 25.183 us |
|
||||
| runtime_snapshot_pressure/runtime_snapshot/256 | 52.193 us | 48.362 us .. 59.051 us |
|
||||
| runtime_snapshot_pressure/runtime_snapshot/64 | 13.701 us | 13.281 us .. 14.100 us |
|
||||
| scheduler_backpressure_pressure/backpressure/128 | 33.341 us | 33.017 us .. 33.630 us |
|
||||
| scheduler_backpressure_pressure/backpressure/64 | 18.659 us | 18.064 us .. 19.492 us |
|
||||
|
||||
## Notes
|
||||
|
||||
- This report is a local comparison anchor, not a cross-host release benchmark.
|
||||
- Memory evidence here is peak working set observed during the benchmark process. Peak handle count is currently only recorded when the runtime can provide it.
|
||||
- The same-host HTTP comparison now covers a narrow single-connection case (split=1) plus a segmented single-file case (split=4) on the same local loopback server model.
|
||||
- Each binary/scenario pair now performs one untimed warmup launch followed by repeated timed samples; the side-by-side table reports median elapsed plus fastest..slowest spread so single-run host noise is less likely to dominate the comparison.
|
||||
- The same-host driver now avoids coarse sleep quantization in its short-process timing and loopback accept path, and it keeps each scenario on one warmed loopback server/port across the timed sample set so Windows first-port cold-path stalls do not dominate the Rust rows.
|
||||
- Small connector-side wins such as no-proxy reqwest client reuse are still better validated through the direct `ARIA2_RUST_PRO_HTTP_TIMING` breakdown than by whole-process elapsed tables alone.
|
||||
- The same-host side-by-side table is strongest as a local regression anchor. Some non-Rust reference rows can still pick up host-local cold-path noise, so this report should not be treated as a precision benchmark without corroborating direct runs.
|
||||
- Shared-runtime multi-download pressure is still represented here through the Rust Criterion anchors rather than the side-by-side table.
|
||||
- The upstream Windows reference now comes from the official aria2 1.37.0 release artifact downloaded into `<repo-root>\dist\upstream\`.
|
||||
@@ -0,0 +1,283 @@
|
||||
# Optimization Ranking
|
||||
|
||||
This file is the current Phase 6 ranking for `aria2-rust-pro` Take 2.
|
||||
|
||||
It is intentionally evidence-first. Each item below exists because current
|
||||
benchmarks, size reports, or runtime traces show a real remaining cost or a
|
||||
real verification gap.
|
||||
|
||||
## Current Ranking
|
||||
|
||||
### 1. Shared-runtime live HTTP fixed cost
|
||||
|
||||
Why it ranks first:
|
||||
|
||||
- this is the hottest still-open product path inside the current Phase 6 work
|
||||
- it already has multiple real wins landed in Take 2
|
||||
- the latest product-side scheduler change removed the previous loose-cap/cache
|
||||
pressure cliff, so remaining work is now narrower fixed-cost work rather than
|
||||
broad fanout underutilization
|
||||
- it is still the clearest place where a product-side win can move the current
|
||||
benchmark surface
|
||||
|
||||
Current evidence:
|
||||
|
||||
- after the latest scheduler and writeback pass, focused Criterion runs now
|
||||
land at:
|
||||
- `loose_cap`: `23.429 .. 23.998 ms`
|
||||
- `tight_cap`: `23.592 .. 24.049 ms`
|
||||
- `tight_cap_6way`: `26.089 .. 26.510 ms`
|
||||
- `cache_pressure_6way_256k`: `20.255 .. 21.380 ms`
|
||||
- after the later CLI config-projection cleanup, exact reruns kept the same
|
||||
`tight_cap` band and pushed the current shared-runtime `6way` absolute band
|
||||
materially lower:
|
||||
- exact `tight_cap`: `23.224 .. 23.603 ms`
|
||||
- exact `tight_cap_6way`: `13.422 .. 13.824 ms`
|
||||
- after the latest small-segment probe and admitted-download segment-budget
|
||||
pass, the current focused shared-runtime band moved again:
|
||||
- `loose_cap`: `12.567 .. 13.399 ms`
|
||||
- `tight_cap`: `12.674 .. 13.071 ms`
|
||||
- `tight_cap_6way`: `13.773 .. 14.212 ms`
|
||||
- `cache_pressure_6way_256k`: `7.793 .. 8.019 ms`
|
||||
- the later broader short bench-surface refresh kept that band and improved it
|
||||
slightly:
|
||||
- `loose_cap`: `11.696 .. 11.935 ms`
|
||||
- `tight_cap`: `11.732 .. 11.957 ms`
|
||||
- `tight_cap_6way`: `12.649 .. 12.855 ms`
|
||||
- `cache_pressure_6way_256k`: `7.137 .. 7.452 ms`
|
||||
- Criterion reports significant improvement in all four shared-runtime lanes:
|
||||
- `loose_cap`: roughly `-7.2% .. -3.4%` wall time
|
||||
- `tight_cap`: roughly `-4.4% .. -1.6%` wall time
|
||||
- `tight_cap_6way`: roughly `-31.9% .. -29.3%` wall time
|
||||
- `cache_pressure_6way_256k`: roughly `-14.9% .. -9.5%` wall time
|
||||
- the new result is a product-path Phase 6 win: runtime now recognizes the
|
||||
upstream-compatible `max-concurrent-downloads` surface, does not throttle
|
||||
already-registered same-runtime HTTP bootstrap work through the smaller
|
||||
active-download queue value, uses even worker partitioning instead of
|
||||
under-filling workers on `6 / 5` style workloads, and collapses segment
|
||||
dispatcher writeback to the final response per download
|
||||
- before that fix, the loopback driver imposed a serialized service-side floor
|
||||
near `96 ms` / `192 ms` because one server worker processed `12` / `24`
|
||||
range requests one at a time with an `8 ms` synthetic response delay
|
||||
- direct timing with `ARIA2_RUST_PRO_HTTP_TIMING=1` showed that, in the shared
|
||||
runtime live HTTP path, the dominant remaining fixed cost was in
|
||||
request/connection/send rather than dispatcher writeback
|
||||
- the same timing probe also confirmed that bootstrap/segment
|
||||
`record_http_transfer_result` work is currently `0 ms` on this host in the
|
||||
hot shared-runtime lane, so further wins need to come from request shape or
|
||||
transport cost rather than from more dispatcher-writeback trimming
|
||||
- the latest exact `tight_cap_6way` timing rerun now shows the hot small-file
|
||||
shared-runtime lane completing all six downloads in the bootstrap request
|
||||
alone:
|
||||
- `planned_segments=0` for every download
|
||||
- `bootstrap_persist_ms=0`
|
||||
- `bootstrap_record_ms=0`
|
||||
- per-request `send_ms` is now typically `10 .. 11 ms` on top of the driver
|
||||
`8 ms` response delay
|
||||
- that means the previous app-side bookkeeping cliff is gone in this lane; the
|
||||
remaining cost is now mostly transport-side send/response floor rather than a
|
||||
large remaining dispatcher or persistence tax
|
||||
- after the latest writeback and segment-tag cleanup, targeted reruns from the
|
||||
current tree show the larger segmented/cache-pressure lane is back in the
|
||||
fast band and the small 6-way lane improves again:
|
||||
- `tight_cap_6way`: `13.008 .. 13.228 ms`
|
||||
- `cache_pressure_6way_256k`: `7.819 .. 7.988 ms`
|
||||
- after the latest reqwest prepared-request contention pass, focused exact
|
||||
reruns stay in the same fast band while trimming one more product-path fixed
|
||||
cost in the shared-runtime connector hot path:
|
||||
- `tight_cap_6way`: mean about `13.117 ms`
|
||||
- `cache_pressure_6way_256k`: mean about `7.900 ms`
|
||||
- root cause for that pass: in concurrent shared-runtime small-file bursts, the
|
||||
private prepared-request cache could become mostly contention cost because
|
||||
many one-shot URI shapes fought over the same mutex before any real reuse
|
||||
existed
|
||||
- the current connector now treats prepared-request caching as opportunistic:
|
||||
repeated shapes still reuse cached URL/header preparation when the lock is
|
||||
available, but contended callers fall back to local uncached preparation
|
||||
instead of blocking on the cache mutex
|
||||
- this pass specifically addresses the broader segmented workload instead of
|
||||
spending more time on the already near-floor no-follow-up small-file path
|
||||
|
||||
Already-landed wins in this lane:
|
||||
|
||||
- shared default reqwest client reuse for no-proxy traffic
|
||||
- initial probe widened from `bytes=0-0` to the first real segment span
|
||||
- tiny post-probe tails that would previously fan out into three one-alignment
|
||||
follow-up requests are now coalesced into two larger follow-up requests
|
||||
- small-alignment segmented transfers now let the initial range probe cover two
|
||||
complete `max-connection-per-server` windows, reducing real follow-up range
|
||||
request count for small live HTTP transfers
|
||||
- shared-runtime segment fanout now budgets against already-admitted downloads
|
||||
rather than reusing the smaller active-download queue cap after admission
|
||||
- the live reqwest connector now also raises its same-host idle connection
|
||||
budget, keeps idle range-transfer connections warm for short bursts, and
|
||||
enables TCP keepalive; the broader bench-surface rerun kept live HTTP lanes
|
||||
fast after this connector change
|
||||
- `max-concurrent-downloads` is now part of the compat option registry and
|
||||
runtime projection, with an upstream-compatible default of `5`
|
||||
- small static HTTP work sets are partitioned evenly across available workers
|
||||
instead of using contiguous chunks that can under-fill the thread set
|
||||
- shared-runtime follow-up records now update dispatcher state once per
|
||||
download from the final segment response, instead of once per range response
|
||||
- direct URI dispatcher registration
|
||||
- incremental verified-prefix writeback
|
||||
- shared-runtime follow-up dispatch through one connection-budgeted segment
|
||||
batch
|
||||
- no-clone first-attempt retry fast path
|
||||
- concurrent loopback segment-server handling in the Criterion suite, which
|
||||
prevents synthetic service-side serialization from hiding client/runtime
|
||||
concurrency
|
||||
- shared-runtime follow-up segments now execute through one batched fanout based
|
||||
on active downloads and `max-connection-per-server`, instead of spawning
|
||||
nested per-download segment workers during bootstrap preparation
|
||||
- live streamed response sinks no longer perform an explicit file flush after
|
||||
every `reqwest::blocking::Response::copy_to`; write/copy errors are still
|
||||
surfaced, while range-heavy live transfers avoid a repeated per-response
|
||||
writeback tax
|
||||
- shared-runtime segment batches now carry the download index as the tag and
|
||||
store each segment target path once per download, removing one `PathBuf` clone
|
||||
per planned segment and reducing batch-result allocation churn
|
||||
- reqwest prepared live-request caching now falls back to local request
|
||||
preparation when the shared cache lock is contended, which keeps repeated
|
||||
range-request reuse available without forcing one-shot concurrent request
|
||||
bursts to wait on the cache mutex
|
||||
|
||||
Explicitly not counted as a measured shared-runtime win yet:
|
||||
|
||||
- proxy-specific reqwest clients are cached by proxy config, but there is still
|
||||
no dedicated proxy-path benchmark proving its standalone impact; keep it as
|
||||
sensible hot-path cleanup rather than counting it as ranked measured evidence
|
||||
|
||||
What still looks promising:
|
||||
|
||||
- lower per-request request/connection/send overhead
|
||||
- more disciplined validation of where blocking reqwest still pays fixed cost
|
||||
- only product-path reductions, not benchmark-only cosmetics
|
||||
|
||||
What has already been tried and rejected:
|
||||
|
||||
- forcing shared-runtime follow-up parallelism to honor the global overall cap
|
||||
regressed the lane by about `9% .. 10%`
|
||||
- swapping the local worker batches to rayon did not produce a meaningful win
|
||||
- leaking prepared-request state into the public `HttpRequestModel` was rejected;
|
||||
the kept version confines reqwest-specific URL/header preparation cache state
|
||||
to `ReqwestHttpConnector`
|
||||
|
||||
### 2. Binary size pressure from the RPC + HTTP/TLS stack
|
||||
|
||||
Why it ranks second:
|
||||
|
||||
- size evidence is now in-tree and clearly points at one dominant cluster
|
||||
- the current binary is already smaller than both the checked C++ Pro Core and
|
||||
the upstream Windows binary, so this is no longer emergency work
|
||||
- there is still a clear future size lane, but it is less urgent than the live
|
||||
shared-runtime HTTP hot path
|
||||
|
||||
Current evidence:
|
||||
|
||||
- current Windows Rust binary: `4.94 MiB` (`5,184,512` bytes)
|
||||
- current checked upstream Windows aria2 binary: `5.39 MiB`
|
||||
- current checked C++ Pro Core binary: `10.88 MiB`
|
||||
- top `cargo bloat --crates` buckets are:
|
||||
- `aria2_rust_pro_rpc`
|
||||
- `reqwest`
|
||||
- `rustls`
|
||||
- `std`
|
||||
- `aria2_rust_pro_protocol`
|
||||
|
||||
Interpretation:
|
||||
|
||||
- deeper size work should focus on the combined RPC + HTTP/TLS surface
|
||||
- one recent owned-code win already landed inside the CLI bucket by replacing
|
||||
repeated config `BTreeMap<String, String>` materialization with direct
|
||||
last-wins directive lookup, which notably shrank
|
||||
`derive_http_session`, `derive_runtime_config`, and
|
||||
`build_ftp_transfer_parts`
|
||||
- current CLI-side LLVM IR evidence is refreshed at `53,272` total lines across
|
||||
`307` function copies, down from the older `59,204` / `320` snapshot
|
||||
- this is now a ranked future optimization lane, not a closure blocker by
|
||||
itself
|
||||
|
||||
### 3. RPC pressure guard depth
|
||||
|
||||
Why it ranks third:
|
||||
|
||||
- current synthetic RPC responsiveness evidence now covers both a deterministic
|
||||
integration guard and Criterion pressure anchors
|
||||
- this remains a ranked lane because the workload is still synthetic and should
|
||||
not be overclaimed as a public-swarm certification
|
||||
- it is no longer an immediate Phase 6 evidence blocker
|
||||
|
||||
Current evidence:
|
||||
|
||||
- the current pressure guards:
|
||||
- repeated `tellStatus`
|
||||
- sampled `getFiles`
|
||||
- repeated `tellActive`
|
||||
- repeated `tellGlobalStat`
|
||||
- BT-like synthetic runtime churn
|
||||
- the denser mixed guard now covers 96 BT-like magnet tasks over 6 rounds,
|
||||
including 576 `tellStatus` calls and 72 sampled `getFiles` calls under
|
||||
per-download runtime tick churn
|
||||
- current Criterion anchors include:
|
||||
- `rpc_mixed_pressure/mixed_rpc/96`: `92.383 us`
|
||||
- `rpc_mixed_pressure/mixed_rpc/192`: `175.169 us`
|
||||
- `bt_visibility_pressure/bt_visibility/32`: `2.3293 ms`
|
||||
- `bt_visibility_pressure/bt_visibility/64`: `2.1302 ms`
|
||||
- the current guard is documented in `rpc-pressure-evidence.md`
|
||||
- that document explicitly says the thresholds are broad and not a final
|
||||
performance certification
|
||||
|
||||
Needed future expansion:
|
||||
|
||||
- higher scheduler pressure
|
||||
- clearer resource counters suitable for long-term perf reporting
|
||||
|
||||
### 4. Same-host comparison noise and interpretation discipline
|
||||
|
||||
Why it still matters:
|
||||
|
||||
- the local comparison report is now useful and much less misleading than it
|
||||
used to be
|
||||
- but it is still a whole-process host-local comparison, not a precision
|
||||
microbenchmark
|
||||
|
||||
Current evidence:
|
||||
|
||||
- `local-comparison.md` now reports medians and spread after warmup
|
||||
- the driver no longer suffers from coarse accept/sleep quantization
|
||||
- the Rust rows now complete with matching payload size and SHA256
|
||||
|
||||
Interpretation:
|
||||
|
||||
- this report is good enough to act as a local regression anchor
|
||||
- it should not be overclaimed as precise proof for micro-optimizations
|
||||
|
||||
## Current Phase 6 Read
|
||||
|
||||
What is already true:
|
||||
|
||||
- benchmark evidence exists
|
||||
- size/bloat evidence exists
|
||||
- multiple real product-side wins are already landed and documented
|
||||
- the current hottest open lane is identified and ranked
|
||||
- non-HTTP RPC and BT-visibility pressure now have current deterministic and
|
||||
Criterion evidence
|
||||
- the Phase 6 shared-runtime loose-cap/cache cliff is fixed by product code,
|
||||
not by benchmark-only masking
|
||||
- current broader bench, bloat, binary-size, and LLVM-lines evidence are now
|
||||
synchronized with the latest Phase 6 tree
|
||||
|
||||
What is not yet honest to claim:
|
||||
|
||||
- that the shared-runtime live HTTP lane is fully exhausted
|
||||
- that size work is fully exhausted
|
||||
- that the current RPC pressure guard is a public-network performance
|
||||
certification
|
||||
|
||||
## References
|
||||
|
||||
- `progress.md`
|
||||
- `docs\perf\local-comparison.md`
|
||||
- `docs\perf\rpc-pressure-evidence.md`
|
||||
- `docs\perf\size-evidence.md`
|
||||
@@ -0,0 +1,82 @@
|
||||
# RPC Pressure Evidence
|
||||
|
||||
This file records the current synthetic RPC responsiveness guard for
|
||||
`aria2-rust-pro`.
|
||||
|
||||
## Scope
|
||||
|
||||
Current guard coverage is synthetic but no longer limited to a single
|
||||
`tellStatus` loop:
|
||||
|
||||
- in-process dispatcher
|
||||
- BT-like magnet workload
|
||||
- repeated `aria2.tellStatus`
|
||||
- sampled `aria2.getFiles`
|
||||
- repeated `aria2.tellActive`
|
||||
- repeated `aria2.tellGlobalStat`
|
||||
- Criterion `rpc_mixed_pressure` and `bt_visibility_pressure` anchors
|
||||
|
||||
This is not a public-swarm benchmark. It is a deterministic regression guard
|
||||
for scheduler/RPC responsiveness while the runtime is still approximation-heavy.
|
||||
|
||||
## Guard Tests
|
||||
|
||||
- `rpc_bt_pressure_guard_keeps_status_active_and_global_stat_responsive`
|
||||
- `rpc_bt_mixed_pressure_guard_covers_churned_status_files_and_global_views`
|
||||
|
||||
Basic guard shape:
|
||||
|
||||
- 64 BT-like magnet tasks
|
||||
- 4 pressure rounds
|
||||
- 256 total `tellStatus` calls
|
||||
- 4 `tellActive` calls
|
||||
- 4 `tellGlobalStat` calls
|
||||
- runtime tick updates injected during the loop to keep non-zero BT-like state
|
||||
|
||||
Mixed guard shape:
|
||||
|
||||
- 96 BT-like magnet tasks
|
||||
- 6 pressure rounds
|
||||
- 576 total `tellStatus` calls
|
||||
- 72 sampled `getFiles` calls
|
||||
- 6 `tellActive` calls
|
||||
- 6 `tellGlobalStat` calls
|
||||
- per-download runtime tick churn before every status probe
|
||||
|
||||
## Current Thresholds
|
||||
|
||||
These thresholds are deliberately broad. They are there to catch obvious
|
||||
regressions, not to certify final performance:
|
||||
|
||||
- cumulative `tellStatus` time across the run: `<= 2000ms`
|
||||
- cumulative `tellActive` time across the run: `<= 500ms`
|
||||
- cumulative `tellGlobalStat` time across the run: `<= 500ms`
|
||||
- cumulative mixed guard time across the run: `<= 4000ms`
|
||||
|
||||
## Current Criterion Anchors
|
||||
|
||||
Current focused Criterion runs on this host:
|
||||
|
||||
| Benchmark | Mean | 95% CI |
|
||||
| --- | ---: | ---: |
|
||||
| `rpc_mixed_pressure/mixed_rpc/96` | `92.383 us` | `90.867 .. 93.895 us` |
|
||||
| `rpc_mixed_pressure/mixed_rpc/192` | `175.169 us` | `160.464 .. 192.884 us` |
|
||||
| `bt_visibility_pressure/bt_visibility/32` | `2.3293 ms` | `1.0756 .. 4.0986 ms` |
|
||||
| `bt_visibility_pressure/bt_visibility/64` | `2.1302 ms` | `2.0707 .. 2.2057 ms` |
|
||||
|
||||
Interpretation:
|
||||
|
||||
- the deterministic integration tests now cover mixed BT/RPC status, file, and
|
||||
global-stat surfaces under runtime churn
|
||||
- the Criterion anchors give a current non-HTTP performance regression guard
|
||||
- the thresholds remain intentionally broad so host-local noise does not turn a
|
||||
synthetic guard into a flaky gate
|
||||
|
||||
## Next Steps
|
||||
|
||||
Further work should extend this guard with:
|
||||
|
||||
- explicit scheduler tick pressure
|
||||
- resource counters suitable for later perf reporting
|
||||
- a documented comparison against the C++ reference once comparable benchmark
|
||||
suites exist
|
||||
@@ -0,0 +1,137 @@
|
||||
# Size Evidence
|
||||
|
||||
This file records the current binary-size and code-size evidence for
|
||||
`aria2-rust-pro` in Take 2 of the modernization goal.
|
||||
|
||||
## Commands
|
||||
|
||||
```powershell
|
||||
rtk cargo build --release -p aria2-rust-pro-cli --manifest-path .\Cargo.toml -j $env:NUMBER_OF_PROCESSORS
|
||||
rtk cargo bloat --release -p aria2-rust-pro-cli --bin aria2-rust-pro --crates -n 40 -j $env:NUMBER_OF_PROCESSORS
|
||||
rtk cargo rustc --release -p aria2-rust-pro-cli --bin aria2-rust-pro --manifest-path .\Cargo.toml -- --emit=llvm-ir
|
||||
rtk cargo llvm-lines --files target\release\deps\aria2_rust_pro.aria2_rust_pro_cli-d4c445ae209bfe38.aria2_rust_pro_cli.b493e489391677ca-cgu.0.rcgu.o.rcgu.ll
|
||||
```
|
||||
|
||||
## Binary Size Snapshot
|
||||
|
||||
Measured on the current Windows host:
|
||||
|
||||
| Binary | Bytes | MiB |
|
||||
| --- | ---: | ---: |
|
||||
| `aria2-rust-pro.exe` | `5,213,184` | `4.97` |
|
||||
| current C++ Pro Core `aria2c.exe` | `11,412,480` | `10.88` |
|
||||
| upstream Windows `aria2c.exe` | `5,649,408` | `5.39` |
|
||||
|
||||
Observations:
|
||||
|
||||
- the current Rust binary is about `54.3%` smaller than the current C++ Pro Core
|
||||
artifact on this host
|
||||
- the current Rust binary remains about `7.7%` smaller than the upstream
|
||||
Windows aria2 binary as well
|
||||
- the latest reduction came from making the release profile more artifact-shaped:
|
||||
`codegen-units = 1`, `lto = "thin"`, and `strip = "symbols"`
|
||||
- a later Phase 6 config-projection cleanup removed another small tranche by
|
||||
replacing repeated release-path `BTreeMap<String, String>` materialization
|
||||
with last-wins directive lookup on demand
|
||||
- the latest checked tree, after the recent structural scheduler/DHT cleanup,
|
||||
leaves the release artifact at `5,213,184` bytes, up `28,672` bytes from the
|
||||
previous recorded snapshot rather than down
|
||||
- the host artifact still stays below both checked C++ references
|
||||
|
||||
## Cargo Bloat Summary
|
||||
|
||||
Current top crate contributions from `cargo bloat --crates`:
|
||||
|
||||
| Crate | `.text` size |
|
||||
| --- | ---: |
|
||||
| `std` | `815.4 KiB` |
|
||||
| `aria2_rust_pro_rpc` | `488.4 KiB` |
|
||||
| `rustls` | `421.7 KiB` |
|
||||
| `aria2_rust_pro_cli` | `246.7 KiB` |
|
||||
| `aria2_rust_pro_protocol` | `236.3 KiB` |
|
||||
| `reqwest` | `213.9 KiB` |
|
||||
| `ring` | `124.2 KiB` |
|
||||
| `hyper_util` | `107.8 KiB` |
|
||||
| `hyper` | `104.2 KiB` |
|
||||
| `aria2_rust_pro_core` | `100.6 KiB` |
|
||||
| `tokio` | `94.4 KiB` |
|
||||
|
||||
Headline totals from the same run:
|
||||
|
||||
- `.text` section: about `3.6 MiB`
|
||||
- file size from the bloat run: about `5.0 MiB`
|
||||
|
||||
Interpretation:
|
||||
|
||||
- the biggest owned size buckets are `aria2_rust_pro_rpc`,
|
||||
`aria2_rust_pro_protocol`, `aria2_rust_pro_cli`, and `aria2_rust_pro_core`
|
||||
- the biggest third-party buckets are the HTTP/TLS stack:
|
||||
`reqwest`, `rustls`, `hyper`, `hyper_util`, `tokio`, and `ring`
|
||||
- future size work should therefore focus on:
|
||||
- whether the default host binary really needs the full RPC/TLS surface in one
|
||||
always-on artifact
|
||||
- whether reqwest / rustls features can be trimmed without breaking the
|
||||
compatibility contract
|
||||
- whether any always-linked RPC/HTTP helpers can be split or made less eager
|
||||
- whether a future release flow should emit a stripped end-user artifact plus
|
||||
a separate debug-symbol artifact rather than making local release builds do
|
||||
both jobs at once
|
||||
- within the owned CLI bucket, the same config-projection cleanup previously cut several
|
||||
previously ranked helpers materially in the filtered `cargo bloat` view:
|
||||
- `run_from_env`: `31.2 KiB` -> `30.2 KiB`
|
||||
- `projection::derive_http_session`: `8.6 KiB` -> `5.7 KiB`
|
||||
- `projection::derive_runtime_config`: `8.3 KiB` -> `4.0 KiB`
|
||||
- `build_ftp_transfer_parts`: `6.4 KiB` -> `3.9 KiB`
|
||||
|
||||
## LLVM Lines Snapshot
|
||||
|
||||
Direct `cargo llvm-lines --release -p aria2-rust-pro-cli --bin aria2-rust-pro`
|
||||
currently fails on this Windows/MSVC host while linking the temporary
|
||||
`cargo-llvm-lines` crate, with many unresolved external symbols. The project
|
||||
itself still builds in release mode; the failure is limited to that tool's
|
||||
temporary relink path.
|
||||
|
||||
The usable current workaround is:
|
||||
|
||||
1. emit release LLVM IR with `cargo rustc -- --emit=llvm-ir`
|
||||
2. point `cargo llvm-lines --files` at the generated CLI `.ll` file
|
||||
|
||||
That current CLI crate IR snapshot reports:
|
||||
|
||||
- total: `53,272` LLVM IR lines across `307` function copies
|
||||
- top entries:
|
||||
- `runtime_host::execute_run_invocation`: `5,538` lines
|
||||
- `run_from_env`: `4,380` lines
|
||||
- `parallel_http_runtime::execute_parallel_http_entries`: `3,751` lines
|
||||
- `http_runtime::execute_segment_transfers`: `2,364` lines
|
||||
- `http_runtime::execute_tagged_segment_transfers_with_parallelism`: `2,345`
|
||||
lines
|
||||
- `runtime_summary::collect_runtime_execution_summary`: `1,207` lines
|
||||
|
||||
Interpretation:
|
||||
|
||||
- the largest CLI-side IR buckets now line up with the Phase 6 runtime and HTTP
|
||||
transfer paths rather than a random unrelated module
|
||||
- `parallel_http_runtime` remains a legitimate future split/size target, but it
|
||||
is also the path that just delivered the latest shared-runtime performance win
|
||||
- full-workspace release LLVM-lines still needs a non-MSVC or fixed
|
||||
`cargo-llvm-lines` path before it should be treated as a strict gate
|
||||
|
||||
## Take 2 Reading
|
||||
|
||||
For Take 2, the honest conclusion is:
|
||||
|
||||
- size evidence now exists in-tree
|
||||
- one real size-reduction tranche is now landed through the release profile
|
||||
- the Rust host binary is now smaller than both the current C++ Pro Core and
|
||||
the upstream Windows binary checked on this host
|
||||
- the main size pressure comes from the combined RPC + HTTP/TLS stack, not from
|
||||
one surprising internal crate explosion
|
||||
- CLI-side LLVM IR now points at runtime execution and parallel HTTP scheduling
|
||||
as the next owned code-size targets
|
||||
- the latest CLI IR refresh still confirms the earlier config-projection and
|
||||
shared-runtime cleanup reduced total CLI IR from `59,204` to `53,272` lines,
|
||||
but the newest structural tree should now be treated as synchronized mainly
|
||||
through the refreshed release build and `cargo bloat --crates` snapshot above
|
||||
- deeper size reduction remains a future optimization lane, but the Phase 6
|
||||
evidence set is now current enough to rank that work honestly
|
||||
Reference in New Issue
Block a user