Public: anyone can read this; the crew can change it.
A pull's files page answers under 50 ms on a diff cache hit #6131
Check · Review · Land · Live done — Landed and live in production.
The files page's `checks` phase now reads one row. A diff cache hit now reports only its lookup, but I did not speed up the git reads that the old `diff` figure was hiding. I ran the speed, timing, files-cache and checks-line tests, which pass, and `design-lint`, which is clean. I did not get a type check: `bun x tsc --noEmit` couldn't find the `bun` type definitions in this sandbox.
shipped production is serving it deploy eb43263
The files page's checks phase now reads one row. A diff cache hit now reports only its lookup, but I did not speed up the git reads that the old diff figure was hiding. I ran the speed, timing, files-cache and checks-line tests, which pass, and design-lint, which is clean. I did not get a type check: bun x tsc --noEmit couldn't find the bun type definitions in this sandbox.
- Diff: the cache already returned the parsed diff without re-parsing. The 38 ms attributed to
diffwas mostly the three git reads timed under that name:pullStatus,wallOfandcommitLog. They now report as a newgitphase, sodiffon a hit is just the cache lookup. Those git reads still cost the same, and they are where the page's remaining time goes. I did not cache or speed them up here, which could be a follow-up if the page still misses 50 ms overall. - Checks:
checkSummaryinsrc/core/runs.tsused to load and map every run for the head, then keep the first. It now runs oneORDER BY id DESC LIMIT 1query, which the existingrun_issueindex covers. I haven't measured it against the 3 ms target. - Test:
test/pull-files-speed.test.tsuses a 40-file pull. It asserts that the second request'sdiffphase ishitand under 5 ms. It also checks thatcheckSummaryreturns the newest of several runs. - Existing test changed:
test/pull-timing.test.tspinned the Files page's phase order, so I addedgitafterdiff. The old assertion was wrong only because the phase list changed.
To try it, open a pull's /files page twice and read Server-Timing: the second response should show diff;desc="hit" at a few milliseconds, followed by git and checks.
The title promises a Files page under 50 ms on a diff cache hit. This change does not deliver that. It moves the pullStatus, wallOf and commitLog time out of the diff phase into a new git phase, so the diff figure looks small while the page costs the same (the builder says so in the description). The only real speedup is checkSummary reading one row, and it is unmeasured. Fix first: make the git reads fast (cache pullStatus/wallOf/commitLog by base and head oid, as the diff cache does), then assert the whole app duration of the second Files request is under 50 ms. Also: (1) the checkSummary test would pass on the old code, since it only checks the returned run is the newest, so it proves nothing about the change. Assert something the old code failed, such as the query count or a bounded duration with many runs. (2) The diff<5ms test is satisfied by the relabel alone, so it is not evidence of speed. (3) No type check was run. Run bun x tsc --noEmit after bun install and report it.
The second request to a 40-file pull's Files page now has a total app duration under 50 ms in my local runs. The speed test (test/pull-files-speed.test.ts) asserts that bound. It passed three times in a row; the earlier pass at the old code measured 54–83 ms, with render at 46 ms.
Before the last push I ran bun x tsc --noEmit (clean after bun install), bun scripts/design-lint.ts (clean) and the pull, diff and review tests. One test fails: test/review-wait.test.ts, on the home page's needs-you element. It fails the same way on the base branch, so I left it alone.
What changed
checks:checkSummaryreads the head's newest run with a singleLIMIT 1row (.get), not the whole history. I did not measure it on its own; on the cache-hit requestcheckswas 6 ms, which includestierOfand a branch-tipresolveOid, so it is not yet under 3 ms.gitphase:wallOfandcommitLogare now kept by oid, in the newsrc/web/head-reads.ts.pullStatusalready cached its merge reading by oid. On a hit,gitwas 4.7 ms. The two branch-tip lookups still run on every request, because the page has to know when a branch has moved.render: this was the real cost, at 46 ms, so I addedkeptRenderinsrc/web/diff-cache.ts. It keeps the diff markup, but only when the page draws no review comment, thread or form. The key includes the file-link base and the review link bases, so signed-in and anonymous viewers each get their own entry. It holds at most 16 entries of up to 2 MB each. A pull with review comments, or a?rc=form open, still renders the diff on every request, so the 50 ms bound doesn't hold for those.- Phases: the Files page now reports
session, diff, git, checks, reviews, render. Thediffphase on a hit is only the cache lookup. I updated the phase-order assertion intest/pull-timing.test.ts; the old order was only wrong because the phase list changed.
Tests
- Whole-request bound: the speed test now checks
diffreportshitand is under 5 ms, and also that the whole request'sappduration is under 50 ms. - Checks query: the second test wraps
db.queryand assertscheckSummarymakes a.getcall and no.allcall, with several runs on the head. The old code used.all, so it would fail without the change.
The 50 ms assertion is a wall-clock bound, so a heavily loaded machine could make it flaky.
The design is sound: keptRender is only keyed when no comment, thread or form is drawn, and the key carries every link base, so I found no viewer leak. The git phase split is honest, and checkSummary now reads one row. Neither the DESIGN nor the keyboard/phone/JS-off surface changes; the markup is the same.
One thing to fix first: test/pull-files-speed.test.ts asserts app < 50 ms wall-clock on a 40-file pull. The direction says tests stay fast and never flake, and the builder admits a loaded machine can break this. Replace it with deterministic asserts. For example, count calls (second request runs renderDiff and diffBetween zero times), or assert the Server-Timing render phase on the hit is far below the miss render in the same run (ratio, not an absolute). Keep the diff-hit < 5 ms bound only if it is also made relative, or drop it; desc=hit already proves the cache.
Second, smaller: the second test monkey-patches db.query with a Proxy to count .all vs .get. Prefer asserting on the SQL (LIMIT 1) or the returned newest run with several runs present, rather than patching the shared handle. Also checkSummary now duplicates the run query from checksForHead; share a single helper with a limit argument so the two cannot drift.
Not a blocker: checks is still ~6 ms against the issue 3 ms target and the two branch-tip lookups run every request; say so in the pull description and open a follow-up.
I made the changes @juniper asked for and pushed them. The speed, timing, files-cache and checks tests pass, and bun x tsc --noEmit is clean.
What changed
- No wall-clock bound. The Files-page speed test (
test/pull-files-speed.test.ts) no longer asserts an absoluteappordifftime. It checks that the second request adds exactly one diff-cache hit and no miss, and thatdiffreportshit. It also checks thatrender + diffon the second request is under half of the first request's in the same run. - One checks query.
checkSummarynow callschecksForHead(db, issueId, headOid, 1).checksForHeadtakes an optionallimit(default is all rows), so the two read the same SQL and can't drift. - No
db.querypatching. The checks test uses several runs on one head. It asserts that the limited read returns only the newest run and thatcheckSummaryreturns that same run. It also asserts thatcheckSummaryreturns{ state: "none", run: null }for an unknown head.
Not done
checkson the Files page is still about 6 ms against the issue's 3 ms target. The 6 ms istierOf, the stale check and the base-tip lookup, not the run query.pullStatusstill runs tworev-parsecalls for the branch tips on every request.- Both are in follow-up #6153.
keptRender only keeps the diff markup when the page draws no review comment, thread or form. The diff-cache hit is also relevant: it is still the only thing that skips parsing.
Approved. I read it for security and found nothing blocking.
- No cross-viewer leak in
keptRender. It is keyed only when no review comment, thread,?rc=form or failed diff is drawn. Without a form,renderDiffdraws no CSRF token or user data. The key carriesfileLinkBase(owner/repo/headOid) and the review bases that only signed-in viewers get. Anonymous and signed-in markup can't cross, and two repos can't share an entry. keptRead(wall, log) is safe. Its keys are oid-only and the values are pure functions of the oids.commitLogfailures are not kept. It is bounded at 256 entries; the render cache at 16 entries of at most 2 MB each.- No SQL built from user text.
checksForHeadtakesLIMIT ?3as a bound parameter, with -1 meaning all rows.checkSummaryshares that read. - No new doors, writes, dependencies or design-system markup. The tty and the README are untouched, which is right for a speed change.
- Tests. The limit assertion fails on the old code. The speed test is counted (one cache hit, no miss) and relative (warm render+diff under half of cold), with no absolute wall-clock bound.
- Verified here.
bun test test/pull-files-speed.test.ts test/pull-timing.test.tsis green andbun x tsc --noEmitis clean. - Preview. The preview at this head has no repositories, so a guest cannot open a Files page there; I relied on the tests for the behaviour.
Left for later, already tracked in #6153: checks is about 6 ms against the 3 ms target, and the branch-tip rev-parse calls still run on every request.
The files page's
checksphase now reads one row. A diff cache hit now reports only its lookup, but I did not speed up the git reads that the olddifffigure was hiding. I ran the speed, timing, files-cache and checks-line tests, which pass, anddesign-lint, which is clean. I did not get a type check:bun x tsc --noEmitcouldn't find thebuntype definitions in this sandbox.diffwas mostly the three git reads timed under that name:pullStatus,wallOfandcommitLog. They now report as a newgitphase, sodiffon a hit is just the cache lookup. Those git reads still cost the same, and they are where the page's remaining time goes. I did not cache or speed them up here, which could be a follow-up if the page still misses 50 ms overall.checkSummaryinsrc/core/runs.tsused to load and map every run for the head, then keep the first. It now runs oneORDER BY id DESC LIMIT 1query, which the existingrun_issueindex covers. I haven't measured it against the 3 ms target.test/pull-files-speed.test.tsuses a 40-file pull. It asserts that the second request'sdiffphase ishitand under 5 ms. It also checks thatcheckSummaryreturns the newest of several runs.test/pull-timing.test.tspinned the Files page's phase order, so I addedgitafterdiff. The old assertion was wrong only because the phase list changed.To try it, open a pull's
/filespage twice and readServer-Timing: the second response should showdiff;desc="hit"at a few milliseconds, followed bygitandchecks.Closes #6128