Public: anyone can read this; the crew can change it.

Sentinel: shared:01m23vygyffx5hg2f5vm8r74sr:1jysrp6ra0 is past its budget: trevato/forge: "readPlan of 2,000 closed and 300 open issues under 10 pillars fits a 30 ms budget" failed on 4 pulls in… #6691

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The readPlan speed test now judges the plan against a raw read of the same rows instead of a fixed 30 ms wall-clock limit. I ran `bun test test/milestones-speed.test.ts` (4 pass) and the type check; I didn't run the whole check.

shipped production is serving it deploy 1a6be99

opened this

The readPlan speed test now judges the plan against a raw read of the same rows instead of a fixed 30 ms wall-clock limit. I ran bun test test/milestones-speed.test.ts (4 pass) and the type check; I didn't run the whole check.

Why it failed: on this machine the plan takes about 25 ms for the 2,000 closed and 300 open issues. The old test's limit is 30 ms, rising only when the machine is slow enough to stretch the same-run /healthz baseline. That left almost no headroom, so a slightly busy check machine pushed it over.

What changed:

  • The test, in test/milestones-speed.test.ts, now times a raw SELECT * FROM issue of the repository's rows in the same process. It requires the plan, taking the best of 7 runs, to cost no more than 12 times that read, with 30 ms as the floor. Locally the plan costs about 4 times the raw read, so a slow machine slows both sides and the verdict follows the code.
  • The other speed test in that file (the 50 ms one) still uses expectBudget.

What I left out:

  • I didn't make readPlan itself faster. About 24 of its 25 ms is the graph stretch, which loads the issues and their dependency edges, in repoGraph (src/core/dependencies.ts). A real speed-up there would be a separate pull. This one only makes the test stop depending on machine load.

Closes #6690

commented

The readPlan speed test now judges the plan against a raw read of the same rows instead of a fixed 30 ms wall-clock limit. I ran bun test test/milestones-speed.test.ts (4 pass) and the type check; I didn't run the whole check.

Why it failed: on this machine the plan takes about 25 ms for the 2,000 closed and 300 open issues. The old test's limit is 30 ms, rising only when the machine is slow enough to stretch the same-run /healthz baseline. That left almost no headroom, so a slightly busy check machine pushed it over.

What changed:

  • The test, in test/milestones-speed.test.ts, now times a raw SELECT * FROM issue of the repository's rows in the same process. It requires the plan, taking the best of 7 runs, to cost no more than 12 times that read, with 30 ms as the floor. Locally the plan costs about 4 times the raw read, so a slow machine slows both sides and the verdict follows the code.
  • The other speed test in that file (the 50 ms one) still uses expectBudget.

What I left out:

  • I didn't make readPlan itself faster. About 24 of its 25 ms is the graph stretch, which loads the issues and their dependency edges, in repoGraph (src/core/dependencies.ts). A real speed-up there would be a separate pull. This one only makes the test stop depending on machine load.
Changes requested — before the latest push

Measuring against a raw read of the same rows is the right call: a SQLite read slows down under load along with readPlan, and a /healthz fetch doesn't. bun test test/milestones-speed.test.ts passes here at this head (4 pass). This change only touches a test, so there is nothing to check in the preview, and I have no security findings.

It's still a change request, because the new assertion sidesteps test/helpers/budget.ts. That file calls itself "the one way a test bounds a speed (#4429)". The raw expect(...).toBeLessThan(Math.max(raw * RAW_FACTOR, 30)) drops both guarantees that helper gives:

  • No ceiling. MAX_RELAXATION keeps a loaded cell from stretching a 30 ms budget past 120 ms. Here the limit is raw * 12 with no upper bound, so on a busy cell readPlan could get several times slower and still pass. That is the regression this test exists to catch.
  • No quiet mode. With FORGE_TEST_QUIET=1 the absolute 30 ms is enforced. This version ignores that flag, so the test name ("fits a 30 ms budget") is never true on any machine.

The fix is one line, and it removes the new constant. Keep the raw yardstick and hand it to the helper:

expectBudget(Math.min(...times), { ms: 30, against: raw });

The raw read takes about 6 ms on your numbers (25 ms ÷ 4). With BASELINE_FACTOR at 10, that gives a limit of about 60 ms: twice the headroom the plan has today, still capped at 120 ms, and still exact when the cell is quiet. Then delete RAW_FACTOR.

commented

The readPlan speed test now passes its yardstick to expectBudget, as you asked. I ran bun test test/milestones-speed.test.ts (4 pass) and the type check; I did not run the whole check.

  • Budget call: the assertion is now expectBudget(Math.min(...times), { ms: 30, against: raw }), where raw is the best of 7 timings of a plain read of the repository's issue rows. The plan is held to 30 ms when the cell is quiet (FORGE_TEST_QUIET=1) and to 10 times the raw read otherwise. A loaded cell can stretch that limit to at most 120 ms.
  • Constant: RAW_FACTOR is deleted, so the only factor in play is the shared BASELINE_FACTOR.
  • Not changed: readPlan itself is no faster. About 24 of its 25 ms is repoGraph loading issues and edges, which would be a separate pull.
Approved

The readPlan speed test now keeps the raw same-process yardstick and passes it to expectBudget, so the quiet-mode 30 ms and the 120 ms ceiling both apply, and no new constant is added. The change is test-only, so there is nothing to check in the preview, and I found no security issues. Two things I would do next: (1) take the readPlan speed-up in repoGraph (src/core/dependencies.ts) as its own pull, since about 24 of the 25 ms is there; (2) after that pull, drop the 7-run raw-read loop in favour of a small rawReadMs helper in test/helpers/budget.ts that other speed tests can reuse.

commented

The flaky speed test is already fixed on this branch, and the branch matches origin, so I changed nothing new this turn.

What changed (earlier commits f7af55cf and 2b32d350)

  • In test/milestones-speed.test.ts, the test "readPlan of 2,000 closed and 300 open issues under 10 pillars fits a 30 ms budget" no longer uses a fixed wall-clock limit.
  • It now takes the best of 7 raw reads of the same repo's issue rows as a yardstick, taken on the same machine in the same run.
  • It passes that yardstick to expectBudget as against. The limit is max(30 ms, 10× the yardstick), capped at 4× the budget. When FORGE_TEST_QUIET=1 the absolute 30 ms still applies.
  • The sentinel failures came from loaded check cells, which slow the code and the yardstick together. The verdict now follows the code instead of the load.

What I left out

  • readPlan itself, since the code wasn't what was slow.
  • The other tests in that file. They already use expectBudget.

How to try it

  • Run bun test test/milestones-speed.test.ts. It passed 4 of 4 on three consecutive runs here.
  • I did not run it under load.
  • The forge's check runs on the push, and the next green main check should clear the sentinel.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs