irtt-stats now owns the finite/exact retained-memory estimate, exposed as StatsConfig::estimated_retained_bytes(probe_count) -> u64.
The estimator is derived from the crate's actual retention model —
exact-sample vectors, IPDV tracker state, and count-based rolling storage —
rather than from a magic number.
irtt-cli no longer carries an independent bytes-per-probe heuristic; FINITE_STATS_BYTES_PER_PROBE is gone.
Ownership
The boundary this establishes:
irtt-stats knows what it retains, and estimates the retained storage.
irtt-cli knows the expected probe count, the number of targets, when to
warn, the warning thresholds, and the human guidance.
The CLI no longer duplicates knowledge of which TimeMetric fields retain
samples, nor any size assumption about IPDV samples or normalized events.
Estimate semantics
Included:
exact timing samples, for the metrics that actually retain them;
adjacent-sequence IPDV tracking state (sample map, sequence order queue,
completed-pair set);
count-based rolling storage when rolling_count is set, assuming a probe
contributes one send event and one unique reply event.
Excluded:
time-based rolling storage — rolling_time retains whatever arrives inside
its window, which cannot be bounded from a probe count alone without
assuming traffic timing, so it is documented as excluded rather than
silently ignored;
everything outside the crate: sockets, client session state, managed
counters, TUI graph history, rendered output, and caller structures.
SampleMode:
Exact retains one value per metric per measurable reply and keeps
unbounded IPDV state, so the estimate grows linearly with the probe count
(currently ~668 bytes/probe on a 64-bit target).
RunningOnly retains no exact samples and bounds its IPDV state at the
continuous sequence limit, so the estimate reaches a ceiling (~1.6 MiB) and
stops growing. It deliberately does not report exact-mode per-probe growth.
Optional measurements: adjusted RTT, one-way delay, and send/receive IPDV are
only measured when the negotiated session supplies the necessary timestamps.
The estimate assumes all of them are available, which is the upper bound.
Approximation and saturation: sizes come from size_of on the retained types,
with a documented capacity-headroom factor of 2 for the amortized-doubling
containers involved. This is a planning aid, not allocator accounting, and it
errs toward overestimating. The result is deterministic and computed with
saturating arithmetic, so an enormous probe count saturates at u64::MAX
rather than wrapping or panicking.
Behavior
The warning still runs before the managed run starts.
FINITE_STATS_MEMORY_WARNING_BYTES, ..._STRONG_..., and ..._VERY_STRONG_... stay in the CLI, unchanged, along with the existing
wording and guidance.
No statistics retention behavior changed. The only edit in crates/irtt-stats/src/core.rs is making CONTINUOUS_SEQUENCE_LIMIT pub(crate); every TimeMetric::new(..) argument is untouched.
Scope
Deliberately not in this PR:
no new exact medians — send_call, timer_error, and server_processing
still do not retain exact samples in finite mode;
no TimeStats redesign and no change to median_ns availability;
no rolling API changes;
no SampleMode semantic changes;
no client, server, protocol, or TUI behavior changes.
cargo check -p irtt-cli --no-default-features --features server --all-targets --locked
git diff --check
The client and tui feature-only checks emit pre-existing dead-code
warnings for unused helpers in crates/irtt-cli/src/cmd/format.rs, unrelated
to and untouched by this change.
Tests
Added crates/irtt-stats/tests/retention.rs: zero probes, exact-mode
monotonic growth, exact-mode linearity, saturation at u64::MAX, running-only
boundedness, a deterministic finite-config estimate in a plausible range,
count-based rolling sensitivity and its cap, and time-based rolling exclusion.
Two unit tests in retention.rs cover the non-zero per-item components and the
running-only ceiling.
Updated the two CLI tests to go through the new estimator. The target-count
test now derives the threshold-crossing target count from StatsConfig::estimated_retained_bytes and asserts no warning just below it
and a warning at it, so it exercises the boundary and survives future
retention changes instead of pinning the old 500-byte heuristic.
## Summary
- `irtt-stats` now owns the finite/exact retained-memory estimate, exposed as
`StatsConfig::estimated_retained_bytes(probe_count) -> u64`.
- The estimator is derived from the crate's actual retention model —
exact-sample vectors, IPDV tracker state, and count-based rolling storage —
rather than from a magic number.
- `irtt-cli` no longer carries an independent bytes-per-probe heuristic;
`FINITE_STATS_BYTES_PER_PROBE` is gone.
## Ownership
The boundary this establishes:
- `irtt-stats` knows what it retains, and estimates the retained storage.
- `irtt-cli` knows the expected probe count, the number of targets, when to
warn, the warning thresholds, and the human guidance.
The CLI no longer duplicates knowledge of which `TimeMetric` fields retain
samples, nor any size assumption about IPDV samples or normalized events.
## Estimate semantics
Included:
- exact timing samples, for the metrics that actually retain them;
- adjacent-sequence IPDV tracking state (sample map, sequence order queue,
completed-pair set);
- count-based rolling storage when `rolling_count` is set, assuming a probe
contributes one send event and one unique reply event.
Excluded:
- time-based rolling storage — `rolling_time` retains whatever arrives inside
its window, which cannot be bounded from a probe count alone without
assuming traffic timing, so it is documented as excluded rather than
silently ignored;
- everything outside the crate: sockets, client session state, managed
counters, TUI graph history, rendered output, and caller structures.
`SampleMode`:
- `Exact` retains one value per metric per measurable reply and keeps
unbounded IPDV state, so the estimate grows linearly with the probe count
(currently ~668 bytes/probe on a 64-bit target).
- `RunningOnly` retains no exact samples and bounds its IPDV state at the
continuous sequence limit, so the estimate reaches a ceiling (~1.6 MiB) and
stops growing. It deliberately does not report exact-mode per-probe growth.
Optional measurements: adjusted RTT, one-way delay, and send/receive IPDV are
only measured when the negotiated session supplies the necessary timestamps.
The estimate assumes all of them are available, which is the upper bound.
Approximation and saturation: sizes come from `size_of` on the retained types,
with a documented capacity-headroom factor of 2 for the amortized-doubling
containers involved. This is a planning aid, not allocator accounting, and it
errs toward overestimating. The result is deterministic and computed with
saturating arithmetic, so an enormous probe count saturates at `u64::MAX`
rather than wrapping or panicking.
## Behavior
- The warning still runs before the managed run starts.
- `FINITE_STATS_MEMORY_WARNING_BYTES`, `..._STRONG_...`, and
`..._VERY_STRONG_...` stay in the CLI, unchanged, along with the existing
wording and guidance.
- No statistics retention behavior changed. The only edit in
`crates/irtt-stats/src/core.rs` is making `CONTINUOUS_SEQUENCE_LIMIT`
`pub(crate)`; every `TimeMetric::new(..)` argument is untouched.
## Scope
Deliberately not in this PR:
- no new exact medians — `send_call`, `timer_error`, and `server_processing`
still do not retain exact samples in finite mode;
- no `TimeStats` redesign and no change to `median_ns` availability;
- no rolling API changes;
- no `SampleMode` semantic changes;
- no client, server, protocol, or TUI behavior changes.
## Verification
All run locally on this branch, all passing:
- `cargo test -p irtt-stats --all-features --locked`
- `cargo test -p irtt-cli --all-features --locked`
- `cargo fmt --all -- --check`
- `cargo check --workspace --all-targets --all-features --locked`
- `cargo test --workspace --all-targets --all-features --locked`
- `cargo clippy --workspace --all-targets --all-features --locked -- -D warnings`
- `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --locked`
- `cargo check -p irtt-cli --no-default-features --features client --all-targets --locked`
- `cargo check -p irtt-cli --no-default-features --features tui --all-targets --locked`
- `cargo check -p irtt-cli --no-default-features --features server --all-targets --locked`
- `git diff --check`
The `client` and `tui` feature-only checks emit pre-existing dead-code
warnings for unused helpers in `crates/irtt-cli/src/cmd/format.rs`, unrelated
to and untouched by this change.
### Tests
Added `crates/irtt-stats/tests/retention.rs`: zero probes, exact-mode
monotonic growth, exact-mode linearity, saturation at `u64::MAX`, running-only
boundedness, a deterministic finite-config estimate in a plausible range,
count-based rolling sensitivity and its cap, and time-based rolling exclusion.
Two unit tests in `retention.rs` cover the non-zero per-item components and the
running-only ceiling.
Updated the two CLI tests to go through the new estimator. The target-count
test now derives the threshold-crossing target count from
`StatsConfig::estimated_retained_bytes` and asserts no warning just below it
and a warning at it, so it exercises the boundary and survives future
retention changes instead of pinning the old 500-byte heuristic.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
irtt-statsnow owns the finite/exact retained-memory estimate, exposed asStatsConfig::estimated_retained_bytes(probe_count) -> u64.exact-sample vectors, IPDV tracker state, and count-based rolling storage —
rather than from a magic number.
irtt-clino longer carries an independent bytes-per-probe heuristic;FINITE_STATS_BYTES_PER_PROBEis gone.Ownership
The boundary this establishes:
irtt-statsknows what it retains, and estimates the retained storage.irtt-cliknows the expected probe count, the number of targets, when towarn, the warning thresholds, and the human guidance.
The CLI no longer duplicates knowledge of which
TimeMetricfields retainsamples, nor any size assumption about IPDV samples or normalized events.
Estimate semantics
Included:
completed-pair set);
rolling_countis set, assuming a probecontributes one send event and one unique reply event.
Excluded:
rolling_timeretains whatever arrives insideits window, which cannot be bounded from a probe count alone without
assuming traffic timing, so it is documented as excluded rather than
silently ignored;
counters, TUI graph history, rendered output, and caller structures.
SampleMode:Exactretains one value per metric per measurable reply and keepsunbounded IPDV state, so the estimate grows linearly with the probe count
(currently ~668 bytes/probe on a 64-bit target).
RunningOnlyretains no exact samples and bounds its IPDV state at thecontinuous sequence limit, so the estimate reaches a ceiling (~1.6 MiB) and
stops growing. It deliberately does not report exact-mode per-probe growth.
Optional measurements: adjusted RTT, one-way delay, and send/receive IPDV are
only measured when the negotiated session supplies the necessary timestamps.
The estimate assumes all of them are available, which is the upper bound.
Approximation and saturation: sizes come from
size_ofon the retained types,with a documented capacity-headroom factor of 2 for the amortized-doubling
containers involved. This is a planning aid, not allocator accounting, and it
errs toward overestimating. The result is deterministic and computed with
saturating arithmetic, so an enormous probe count saturates at
u64::MAXrather than wrapping or panicking.
Behavior
FINITE_STATS_MEMORY_WARNING_BYTES,..._STRONG_..., and..._VERY_STRONG_...stay in the CLI, unchanged, along with the existingwording and guidance.
crates/irtt-stats/src/core.rsis makingCONTINUOUS_SEQUENCE_LIMITpub(crate); everyTimeMetric::new(..)argument is untouched.Scope
Deliberately not in this PR:
send_call,timer_error, andserver_processingstill do not retain exact samples in finite mode;
TimeStatsredesign and no change tomedian_nsavailability;SampleModesemantic changes;Verification
All run locally on this branch, all passing:
cargo test -p irtt-stats --all-features --lockedcargo test -p irtt-cli --all-features --lockedcargo fmt --all -- --checkcargo check --workspace --all-targets --all-features --lockedcargo test --workspace --all-targets --all-features --lockedcargo clippy --workspace --all-targets --all-features --locked -- -D warningsRUSTDOCFLAGS="-D warnings" cargo doc --workspace --all-features --no-deps --lockedcargo check -p irtt-cli --no-default-features --features client --all-targets --lockedcargo check -p irtt-cli --no-default-features --features tui --all-targets --lockedcargo check -p irtt-cli --no-default-features --features server --all-targets --lockedgit diff --checkThe
clientandtuifeature-only checks emit pre-existing dead-codewarnings for unused helpers in
crates/irtt-cli/src/cmd/format.rs, unrelatedto and untouched by this change.
Tests
Added
crates/irtt-stats/tests/retention.rs: zero probes, exact-modemonotonic growth, exact-mode linearity, saturation at
u64::MAX, running-onlyboundedness, a deterministic finite-config estimate in a plausible range,
count-based rolling sensitivity and its cap, and time-based rolling exclusion.
Two unit tests in
retention.rscover the non-zero per-item components and therunning-only ceiling.
Updated the two CLI tests to go through the new estimator. The target-count
test now derives the threshold-crossing target count from
StatsConfig::estimated_retained_bytesand asserts no warning just below itand a warning at it, so it exercises the boundary and survives future
retention changes instead of pinning the old 500-byte heuristic.