Judge stall reversal by rate over a bounded window #44

Merged
Breadway merged 4 commits from fix/ram-76-stall-window into main 2026-10-14 20:34:24 +08:00
Owner

Closes RAM-76

Found by the RAM-30 live benchmark: a 96 MiB worker under a 16 MiB daemon limit accumulated about 6 s of stall and was never reversed.

Causes, all fixed:

  • The reversal compared a fixed 500,000 us rise between tick deltas, which depends on the tick length and is unreachable at short intervals. It now compares a stall rate (basis points of wall time) and reverses on a one point rise over the frozen pre-write rate. The old stall_delta_verdict, StallVerdict and STALL_SCOPE_DELTA_RISE_US are removed.
  • Only the tick right after a write was judged. Each confirmed limit now has a 10 second observation window that survives duplicate ticks, and a new confirmation replaces the older observation of the same scope.
  • A pass that only put a limit back counted as having written nothing, so the journal was not republished and the rollback never showed in breadram actions. ExecutionPass now carries a reversed count, wrote() includes it, and summary() reports it alongside any attempts.

A soft limit on a scope with a readable pressure file waits one tick until two readings give a pre-write baseline. A scope with no readable pressure file has no signal to wait for, is never reversed, and is not held back, so nothing is starved. Non-soft-limit actions are untouched. A pass that held limits back says so instead of reporting that no action was proposed.

A missing, reset, or zero-duration reading never reverses. The reversal goes through recover_actions, so a value another manager changed is skipped, and a replaced target (new generation) is neither reversed nor kept under observation.

Tests (new): 1 point boundary (99 vs 100 bp), the 10,000 bp cap, equal rates at 250/500/2000/3000 ms ticks, frozen baseline and window expiry, missing/reset/zero-duration readings, and daemon-level tests of the settle step: reversal restores the value, journals a rollback, records Ineffective and counts as a write; an unrisen scope stays observed; a foreign change is not overwritten; a replaced target is dropped; no duplicate observation. Deferral is tested for readable, unreadable and non-soft-limit cases.

Verification: clippy -D warnings clean, cargo test --workspace 591 passed.

Live check (not part of this branch): scripts/bench/bench-daemon.sh from feature/ram-30-benchmarks, run against a build of this head, journals confirmed then rolled_back and exits 0. On main it never reversed.

Closes RAM-76 Found by the RAM-30 live benchmark: a 96 MiB worker under a 16 MiB daemon limit accumulated about 6 s of stall and was never reversed. Causes, all fixed: - The reversal compared a fixed 500,000 us rise between tick deltas, which depends on the tick length and is unreachable at short intervals. It now compares a stall rate (basis points of wall time) and reverses on a one point rise over the frozen pre-write rate. The old stall_delta_verdict, StallVerdict and STALL_SCOPE_DELTA_RISE_US are removed. - Only the tick right after a write was judged. Each confirmed limit now has a 10 second observation window that survives duplicate ticks, and a new confirmation replaces the older observation of the same scope. - A pass that only put a limit back counted as having written nothing, so the journal was not republished and the rollback never showed in `breadram actions`. ExecutionPass now carries a reversed count, wrote() includes it, and summary() reports it alongside any attempts. A soft limit on a scope with a readable pressure file waits one tick until two readings give a pre-write baseline. A scope with no readable pressure file has no signal to wait for, is never reversed, and is not held back, so nothing is starved. Non-soft-limit actions are untouched. A pass that held limits back says so instead of reporting that no action was proposed. A missing, reset, or zero-duration reading never reverses. The reversal goes through recover_actions, so a value another manager changed is skipped, and a replaced target (new generation) is neither reversed nor kept under observation. Tests (new): 1 point boundary (99 vs 100 bp), the 10,000 bp cap, equal rates at 250/500/2000/3000 ms ticks, frozen baseline and window expiry, missing/reset/zero-duration readings, and daemon-level tests of the settle step: reversal restores the value, journals a rollback, records Ineffective and counts as a write; an unrisen scope stays observed; a foreign change is not overwritten; a replaced target is dropped; no duplicate observation. Deferral is tested for readable, unreadable and non-soft-limit cases. Verification: clippy -D warnings clean, cargo test --workspace 591 passed. Live check (not part of this branch): scripts/bench/bench-daemon.sh from feature/ram-30-benchmarks, run against a build of this head, journals confirmed then rolled_back and exits 0. On main it never reversed.
fix: judge stall reversal by rate over a bounded window and publish reversals
All checks were successful
CPU checks / check (push) Successful in 1m25s
db36af288a
Author
Owner

Review of db36af2 (RAM-76). Verdict: changes requested. No merge.

Verified on db36af2: Forgejo status success (CPU checks / check, run 99), local cargo test --workspace --locked pass, cargo clippy --workspace --all-targets --locked -- -D warnings clean, cargo fmt --check clean. No em dashes or attribution in the diff. No existing reviews. Rate math is correct: delta_us10000/(elapsed_ms1000) is basis points of wall time, u128 widening cannot overflow, the 10000 cap and checked_sub/zero-elapsed/reset guards are right. Reversal goes through recover_actions, which only writes while the live value equals last_applied, so it cannot write foreign or missing data; the ActionId/generation filter also drops pending entries for replaced workloads.

Rework checklist:

  1. Stale docs and dead API (blocking). The reversal rule changed but its documentation did not.

    • docs/PRIORITIES.md:63-73 still says "half a CPU-second more stall than the tick before (STALL_SCOPE_DELTA_RISE_US)" and "limited on the previous pass". Describe the rate rule: pre-write baseline frozen at arm(), reverse on a >=100 bp rise inside STALL_OBSERVATION_MS.
    • crates/breadram-core/src/policy/budget.rs:18-26: STALL_SCOPE_DELTA_RISE_US docs describe a per-tick 500,000 us rise, which is no longer the rule.
    • budget.rs:~140-172: the StallWatch and judge() docs still say "rose by at least STALL_SCOPE_DELTA_RISE_US" and "limited on the previous pass"; judge now takes now_ms and has window semantics that are undocumented.
    • stall_delta_verdict, StallVerdict and STALL_SCOPE_DELTA_RISE_US are no longer used by any production path (daemon only uses StallWatch). They survive only in their own unit test and as an arbitrary number in the StallWatch test (budget.rs:313-341, policy/mod.rs:26-27). Remove them (and their re-exports) or make the new rule use them; do not leave a public verdict function documenting a rule the daemon does not apply. The test comment "half a CPU-second more" is stale too.
    • daemon.rs:511-516, 1065-1068, 1161: comments still say "previous pass" / "reversed on the next tick".
  2. Deferral is silent and can starve a limit (blocking). daemon.rs:1025-1028 drops every CgroupSoftLimit action whose scope has no two-sample rate baseline.

    • If a scope never yields a readable memory.pressure (PSI off, controller not delegated, file absent), it is not in scope_pressure_totals, never gets a baseline, and its limit is deferred forever. Before this change a missing signal meant the limit was applied and kept; now it is never applied, with no note. Decide and implement a bounded behavior (for example apply after N ticks with no signal, or an explicit visible note that the limit is held because no stall signal exists), and say which in the docs.
    • Workloads that are not in ControlTargets also lose their soft-limit request entirely, so the executor's journalled refusal (TargetGone/Unsupported) no longer appears. requests_for_plan's own comment says that refusal is more useful than a silent skip. Only defer scopes that are controllable and merely lack a baseline yet.
    • When every action is deferred, execute_plan reports "the plan proposed no action" (execution.rs:210), which is false and is what lands in execution_notes. Push an explicit note per deferred action (for example "soft limit on X deferred until two stall samples exist").
    • A config-change PolicyRuntime::new or panic rebuild resets the watch, so the first limit after either is delayed by two ticks; mention in docs.
  3. The daemon integration has no test (blocking). Every added test exercises StallWatch or ExecutionPass in isolation. Nothing covers the new run_execution logic: judge-before-execute ordering, the has_baseline deferral and its non-soft-limit pass-through, monitor/manual mode, the ownership/ActionId filter, disarm after Restored only, stall_pending retention through the window, a duplicate-tick not re-arming, or reversed feeding wrote(). run_execution is hard-wired to RealFs, so extract pure helpers (stage the plan against the watch and return deferral notes; select ids to reverse; update pending after a pass) and unit-test them. The PR body cites a live run from feature/ram-30-benchmarks, which is not part of this SHA and I could not treat as evidence.

  4. Smaller items (fix with the above or justify):

    • budget.rs: no test at the 99 vs 100 bp boundary or the 10,000 cap. Add them. A baseline >= 9901 bp can never reverse because the rate is capped; note or handle it.
    • daemon.rs:1114-1128: re-arming a scope that is still watched pushes a second (scope,id) pair into stall_pending; replace the existing entry instead.
    • daemon.rs: the denominator is snapshot observed_at_ms but the counters are read later in run_execution. At 250 ms ticks a few ms of read jitter is comparable to the 1 point threshold. Take the timestamp at the counter read (clock.monotonic_ms()) for judge.
    • execution.rs summary(): a mixed pass (results and reversed > 0) summarizes only the attempts, and execution_notes shows the summary instead of pass.notes when wrote(), so the reversal is invisible. Include reversed in the mixed-case summary.

Out of scope for rework: nothing else; scope of the diff is otherwise tight.

Review of db36af2 (RAM-76). Verdict: changes requested. No merge. Verified on db36af2: Forgejo status success (CPU checks / check, run 99), local `cargo test --workspace --locked` pass, `cargo clippy --workspace --all-targets --locked -- -D warnings` clean, `cargo fmt --check` clean. No em dashes or attribution in the diff. No existing reviews. Rate math is correct: delta_us*10000/(elapsed_ms*1000) is basis points of wall time, u128 widening cannot overflow, the 10000 cap and checked_sub/zero-elapsed/reset guards are right. Reversal goes through recover_actions, which only writes while the live value equals last_applied, so it cannot write foreign or missing data; the ActionId/generation filter also drops pending entries for replaced workloads. Rework checklist: 1. Stale docs and dead API (blocking). The reversal rule changed but its documentation did not. - docs/PRIORITIES.md:63-73 still says "half a CPU-second more stall than the tick before (STALL_SCOPE_DELTA_RISE_US)" and "limited on the previous pass". Describe the rate rule: pre-write baseline frozen at arm(), reverse on a >=100 bp rise inside STALL_OBSERVATION_MS. - crates/breadram-core/src/policy/budget.rs:18-26: STALL_SCOPE_DELTA_RISE_US docs describe a per-tick 500,000 us rise, which is no longer the rule. - budget.rs:~140-172: the StallWatch and judge() docs still say "rose by at least STALL_SCOPE_DELTA_RISE_US" and "limited on the previous pass"; judge now takes now_ms and has window semantics that are undocumented. - stall_delta_verdict, StallVerdict and STALL_SCOPE_DELTA_RISE_US are no longer used by any production path (daemon only uses StallWatch). They survive only in their own unit test and as an arbitrary number in the StallWatch test (budget.rs:313-341, policy/mod.rs:26-27). Remove them (and their re-exports) or make the new rule use them; do not leave a public verdict function documenting a rule the daemon does not apply. The test comment "half a CPU-second more" is stale too. - daemon.rs:511-516, 1065-1068, 1161: comments still say "previous pass" / "reversed on the next tick". 2. Deferral is silent and can starve a limit (blocking). daemon.rs:1025-1028 drops every CgroupSoftLimit action whose scope has no two-sample rate baseline. - If a scope never yields a readable memory.pressure (PSI off, controller not delegated, file absent), it is not in scope_pressure_totals, never gets a baseline, and its limit is deferred forever. Before this change a missing signal meant the limit was applied and kept; now it is never applied, with no note. Decide and implement a bounded behavior (for example apply after N ticks with no signal, or an explicit visible note that the limit is held because no stall signal exists), and say which in the docs. - Workloads that are not in ControlTargets also lose their soft-limit request entirely, so the executor's journalled refusal (TargetGone/Unsupported) no longer appears. requests_for_plan's own comment says that refusal is more useful than a silent skip. Only defer scopes that are controllable and merely lack a baseline yet. - When every action is deferred, execute_plan reports "the plan proposed no action" (execution.rs:210), which is false and is what lands in execution_notes. Push an explicit note per deferred action (for example "soft limit on X deferred until two stall samples exist"). - A config-change PolicyRuntime::new or panic rebuild resets the watch, so the first limit after either is delayed by two ticks; mention in docs. 3. The daemon integration has no test (blocking). Every added test exercises StallWatch or ExecutionPass in isolation. Nothing covers the new run_execution logic: judge-before-execute ordering, the has_baseline deferral and its non-soft-limit pass-through, monitor/manual mode, the ownership/ActionId filter, disarm after Restored only, stall_pending retention through the window, a duplicate-tick not re-arming, or reversed feeding wrote(). run_execution is hard-wired to RealFs, so extract pure helpers (stage the plan against the watch and return deferral notes; select ids to reverse; update pending after a pass) and unit-test them. The PR body cites a live run from feature/ram-30-benchmarks, which is not part of this SHA and I could not treat as evidence. 4. Smaller items (fix with the above or justify): - budget.rs: no test at the 99 vs 100 bp boundary or the 10,000 cap. Add them. A baseline >= 9901 bp can never reverse because the rate is capped; note or handle it. - daemon.rs:1114-1128: re-arming a scope that is still watched pushes a second (scope,id) pair into stall_pending; replace the existing entry instead. - daemon.rs: the denominator is snapshot observed_at_ms but the counters are read later in run_execution. At 250 ms ticks a few ms of read jitter is comparable to the 1 point threshold. Take the timestamp at the counter read (clock.monotonic_ms()) for judge. - execution.rs summary(): a mixed pass (results and reversed > 0) summarizes only the attempts, and execution_notes shows the summary instead of pass.notes when wrote(), so the reversal is invisible. Include reversed in the mixed-case summary. Out of scope for rework: nothing else; scope of the diff is otherwise tight.
fix: address review of the stall window change
All checks were successful
CPU checks / check (push) Successful in 2m39s
0c039496fc
Author
Owner

Rework pushed as 0c03949 for all three blockers and the smaller items: docs and dead API removed (PRIORITIES.md, budget.rs, daemon comments, policy re-exports); deferral no longer starves or silently drops (unreadable scopes are not held back, a deferral note replaces the false 'no action' note, helper is unit tested); the reversal and arming logic is extracted into settle_stall_observations with daemon-level tests; boundary and cap tests, the duplicate-arm fix, and summary() reporting reversals are added. The PR body now labels the live bench as external evidence. Not changed: now_ms is still the snapshot timestamp, so jitter at 250 ms ticks stays close to the 1 point threshold; the default tick is 3 s and the bench uses 2 s. Requesting a fresh review of 0c03949.

Rework pushed as 0c03949 for all three blockers and the smaller items: docs and dead API removed (PRIORITIES.md, budget.rs, daemon comments, policy re-exports); deferral no longer starves or silently drops (unreadable scopes are not held back, a deferral note replaces the false 'no action' note, helper is unit tested); the reversal and arming logic is extracted into settle_stall_observations with daemon-level tests; boundary and cap tests, the duplicate-arm fix, and summary() reporting reversals are added. The PR body now labels the live bench as external evidence. Not changed: now_ms is still the snapshot timestamp, so jitter at 250 ms ticks stays close to the 1 point threshold; the default tick is 3 s and the bench uses 2 s. Requesting a fresh review of 0c03949.
Author
Owner

Review of 0c03949 (RAM-76). Verdict: changes requested. No merge.

Verified on exactly 0c039496fc in a scratch clone: cargo test --workspace --locked all green (416 core tests, no failures), cargo clippy --workspace --all-targets --locked -- -D warnings clean, cargo fmt --check clean. Forgejo status for this SHA: success ('CPU checks / check (push)'). No em dashes or AI attribution in the diff, commits or PR body.

Blocker 1: stale docs remain (one blocker left)

  • docs/PRIORITIES.md lines 107-110 (the benchmark paragraph) still say: "the verdict on these runs is Keep: the accumulation stays below the half CPU-second the daemon reverses on. A scope that accumulates past it is Reverse and only its limit is put back." That is the removed rule (STALL_SCOPE_DELTA_RISE_US, 500,000 us per tick) and the removed StallVerdict vocabulary. It now contradicts lines 63-90 of the same file. Rewrite it against the rate rule: a one point (100 bp) rise over the frozen pre-write rate inside the 10 s window. The measured table is a per-run accumulation, so say whether those runs would have stayed under the rate threshold or drop the verdict sentence.

Everything else on this item is fixed: grep finds no stall_delta_verdict, StallVerdict or STALL_SCOPE_DELTA_RISE_US anywhere in source or docs, policy/mod.rs re-exports STALL_OBSERVATION_MS and STALL_RISE_BASIS_POINTS, and the budget.rs and daemon comments match the new behavior.

Blocker 2: deferral (pass)

defer_unbaselined_limits (daemon.rs 1257-1279) holds a soft limit only when the scope is in totals (readable pressure file) and has no baseline. An unreadable scope is never held back, so it cannot be starved. Only CgroupSoftLimit is filtered. The 'the plan proposed no action' note is removed and replaced by a deferral note when limits were deferred. A non-controllable scope is never in totals (scope_pressure_totals iterates controllable targets only), so it is not deferred and still reaches execute_plan and gets its journalled refusal. One tick of deferral is acceptable: it costs one monitor interval before relief and is what makes the baseline genuinely pre-write. Three unit tests cover readable, unreadable and non-soft-limit cases.

Blocker 3: tests for the run_execution changes (pass)

settle_stall_observations (StallBooks) is extracted and tested at daemon level with a LiveValueExecutor that really tracks the live value. I mutated the code in my scratch clone to check the tests bite:

  • removing pass.reversed += put_back fails a_risen_scope_is_put_back_recorded_ineffective_and_published
  • removing the same_target filter fails a_replaced_target_is_neither_reversed_nor_kept_under_observation
  • removing the re-arm retain fails a_new_confirmation_replaces_the_older_observation_of_the_same_scope
  • removing stall_watch.disarm fails the reversal test
  • removing the Ineffective record is caught (the test asserts on it)
    The reversal test asserts the value goes back to max, a RolledBack journal entry, an Ineffective history record, pending empty, and wrote() true. The foreign-change test asserts the live value is untouched.

Remaining untested wiring: run_execution itself (judge-before-execute order, passing totals into the filter) still touches the real filesystem. Acceptable for this PR: the pieces are individually tested, the order is a few lines with a comment, and the PR body cites the RAM-30 live bench as external evidence (not part of this branch, I did not rerun it). I would welcome a follow-up that injects the pressure reader, but I am not requiring it.

Smaller items (pass)

99 vs 100 bp boundary test, 10,000 bp cap test, equal rate at 250/500/2000/3000 ms, duplicate (scope,id) push on re-arm, and summary() showing reversals next to attempts are all present and pass.

Known unaddressed: now_ms jitter

Not blocking. Default tick is 3 s and the minimum is 250 ms, where read-latency jitter could be close to the 1 point threshold. Filed as RAM-78 (Forgejo #45).

Next action

Fix the PRIORITIES.md paragraph above and push. That is a docs-only change, so the re-review is quick: re-run grep for Reverse, half CPU-second and 500,000 across docs, confirm CI green on the new head, then merge.

Review of 0c03949 (RAM-76). Verdict: changes requested. No merge. Verified on exactly 0c039496fc84b30961d9ae8c858d8d702f161eea in a scratch clone: cargo test --workspace --locked all green (416 core tests, no failures), cargo clippy --workspace --all-targets --locked -- -D warnings clean, cargo fmt --check clean. Forgejo status for this SHA: success ('CPU checks / check (push)'). No em dashes or AI attribution in the diff, commits or PR body. ## Blocker 1: stale docs remain (one blocker left) - docs/PRIORITIES.md lines 107-110 (the benchmark paragraph) still say: "the verdict on these runs is Keep: the accumulation stays below the half CPU-second the daemon reverses on. A scope that accumulates past it is Reverse and only its limit is put back." That is the removed rule (STALL_SCOPE_DELTA_RISE_US, 500,000 us per tick) and the removed StallVerdict vocabulary. It now contradicts lines 63-90 of the same file. Rewrite it against the rate rule: a one point (100 bp) rise over the frozen pre-write rate inside the 10 s window. The measured table is a per-run accumulation, so say whether those runs would have stayed under the rate threshold or drop the verdict sentence. Everything else on this item is fixed: grep finds no stall_delta_verdict, StallVerdict or STALL_SCOPE_DELTA_RISE_US anywhere in source or docs, policy/mod.rs re-exports STALL_OBSERVATION_MS and STALL_RISE_BASIS_POINTS, and the budget.rs and daemon comments match the new behavior. ## Blocker 2: deferral (pass) defer_unbaselined_limits (daemon.rs 1257-1279) holds a soft limit only when the scope is in `totals` (readable pressure file) and has no baseline. An unreadable scope is never held back, so it cannot be starved. Only CgroupSoftLimit is filtered. The 'the plan proposed no action' note is removed and replaced by a deferral note when limits were deferred. A non-controllable scope is never in `totals` (scope_pressure_totals iterates controllable targets only), so it is not deferred and still reaches execute_plan and gets its journalled refusal. One tick of deferral is acceptable: it costs one monitor interval before relief and is what makes the baseline genuinely pre-write. Three unit tests cover readable, unreadable and non-soft-limit cases. ## Blocker 3: tests for the run_execution changes (pass) settle_stall_observations (StallBooks) is extracted and tested at daemon level with a LiveValueExecutor that really tracks the live value. I mutated the code in my scratch clone to check the tests bite: - removing `pass.reversed += put_back` fails a_risen_scope_is_put_back_recorded_ineffective_and_published - removing the same_target filter fails a_replaced_target_is_neither_reversed_nor_kept_under_observation - removing the re-arm retain fails a_new_confirmation_replaces_the_older_observation_of_the_same_scope - removing stall_watch.disarm fails the reversal test - removing the Ineffective record is caught (the test asserts on it) The reversal test asserts the value goes back to max, a RolledBack journal entry, an Ineffective history record, pending empty, and wrote() true. The foreign-change test asserts the live value is untouched. Remaining untested wiring: run_execution itself (judge-before-execute order, passing `totals` into the filter) still touches the real filesystem. Acceptable for this PR: the pieces are individually tested, the order is a few lines with a comment, and the PR body cites the RAM-30 live bench as external evidence (not part of this branch, I did not rerun it). I would welcome a follow-up that injects the pressure reader, but I am not requiring it. ## Smaller items (pass) 99 vs 100 bp boundary test, 10,000 bp cap test, equal rate at 250/500/2000/3000 ms, duplicate (scope,id) push on re-arm, and summary() showing reversals next to attempts are all present and pass. ## Known unaddressed: now_ms jitter Not blocking. Default tick is 3 s and the minimum is 250 ms, where read-latency jitter could be close to the 1 point threshold. Filed as RAM-78 (Forgejo #45). ## Next action Fix the PRIORITIES.md paragraph above and push. That is a docs-only change, so the re-review is quick: re-run grep for `Reverse`, `half CPU-second` and `500,000` across docs, confirm CI green on the new head, then merge.
docs: describe the budget measurements against the stall rate rule
Some checks failed
CPU checks / check (push) Has been cancelled
ee9b3dcd0a
fix: stop measure-budget claiming a reversal verdict the daemon no longer uses
All checks were successful
CPU checks / check (push) Successful in 1m10s
2ec367a8f8
Author
Owner

Review of 2ec367a8f8 (RAM-76). Verdict: pass.

Verified in a fresh scratch clone checked out at exactly this SHA (git ls-remote confirmed the branch head before and after; base main is 91e49c2).

  1. Removed rule: grep of the whole tree (crates, docs, scripts, README, examples, ci, packaging, .forgejo) for STALL_SCOPE_DELTA_RISE_US, stall_delta_verdict, StallVerdict, "half a CPU", "half CPU", "Reverse verdict", "stall verdict", DELTA_RISE and 500_000 finds no live reference. The only residue is a test comment in policy/budget.rs (line 353, "half a CPU-second more stall in one second reverses") which describes a 50% rate rise and is accurate for the rate rule, plus unrelated 500_000 literals in activity.rs and a cli test. Nothing in .forgejo or ci references measure-budget.sh.
  2. docs/PRIORITIES.md: the rewritten paragraph matches the code. STALL_RISE_BASIS_POINTS = 100 (budget.rs:28), STALL_OBSERVATION_MS = 10_000 (budget.rs:112), baseline frozen at arm(), rate in basis points of wall time, deferral for readable scopes only (daemon.rs defer_unbaselined_limits), recover_actions plus Ineffective. The benchmark paragraph now says the recorded numbers predate the rate rule, were not replayed through it, and are a record of cost, not a verdict. No overclaim.
  3. scripts/measure-budget.sh: ran it, exit 0, prints "ok". The new line is total / 400,000 us as a percentage, informational only; 274141/400000 = 68.5% as stated. My run printed tight=70.2% from 280666 us, consistent with the formula and with the run-to-run variation already recorded in the doc.
  4. cargo test --workspace --locked: exit 0, 591 passed, 0 failed. cargo clippy --workspace --all-targets --locked -- -D warnings: exit 0. cargo fmt --check: exit 0.
  5. CI: "CPU checks / check (push)" is success on exactly 2ec367a (run 102, Successful in 1m10s).
  6. No em dashes and no AI attribution in the diff, the four commit messages, or the PR body.

Prior blockers: db36af2 (comment 4848) and 0c03949 (comment 4883, PRIORITIES.md benchmark paragraph) are resolved. All other items passed at 0c03949 and the two later commits touch only docs/PRIORITIES.md and scripts/measure-budget.sh. There are no formal reviews outstanding on the PR. Known non-blocking follow-up RAM-78 (now_ms jitter) is filed.

Merging with merge commit and deleting the head branch under the user's merge authorization for breadram.

Review of 2ec367a8f8c731779db181fbfd892358912a192f (RAM-76). Verdict: pass. Verified in a fresh scratch clone checked out at exactly this SHA (git ls-remote confirmed the branch head before and after; base main is 91e49c2). 1. Removed rule: grep of the whole tree (crates, docs, scripts, README, examples, ci, packaging, .forgejo) for STALL_SCOPE_DELTA_RISE_US, stall_delta_verdict, StallVerdict, "half a CPU", "half CPU", "Reverse verdict", "stall verdict", DELTA_RISE and 500_000 finds no live reference. The only residue is a test comment in policy/budget.rs (line 353, "half a CPU-second more stall in one second reverses") which describes a 50% rate rise and is accurate for the rate rule, plus unrelated 500_000 literals in activity.rs and a cli test. Nothing in .forgejo or ci references measure-budget.sh. 2. docs/PRIORITIES.md: the rewritten paragraph matches the code. STALL_RISE_BASIS_POINTS = 100 (budget.rs:28), STALL_OBSERVATION_MS = 10_000 (budget.rs:112), baseline frozen at arm(), rate in basis points of wall time, deferral for readable scopes only (daemon.rs defer_unbaselined_limits), recover_actions plus Ineffective. The benchmark paragraph now says the recorded numbers predate the rate rule, were not replayed through it, and are a record of cost, not a verdict. No overclaim. 3. scripts/measure-budget.sh: ran it, exit 0, prints "ok". The new line is total / 400,000 us as a percentage, informational only; 274141/400000 = 68.5% as stated. My run printed tight=70.2% from 280666 us, consistent with the formula and with the run-to-run variation already recorded in the doc. 4. cargo test --workspace --locked: exit 0, 591 passed, 0 failed. cargo clippy --workspace --all-targets --locked -- -D warnings: exit 0. cargo fmt --check: exit 0. 5. CI: "CPU checks / check (push)" is success on exactly 2ec367a (run 102, Successful in 1m10s). 6. No em dashes and no AI attribution in the diff, the four commit messages, or the PR body. Prior blockers: db36af2 (comment 4848) and 0c03949 (comment 4883, PRIORITIES.md benchmark paragraph) are resolved. All other items passed at 0c03949 and the two later commits touch only docs/PRIORITIES.md and scripts/measure-budget.sh. There are no formal reviews outstanding on the PR. Known non-blocking follow-up RAM-78 (now_ms jitter) is filed. Merging with merge commit and deleting the head branch under the user's merge authorization for breadram.
Breadway deleted branch fix/ram-76-stall-window 2026-10-14 20:34:24 +08:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Breadway/breadram!44
No description provided.