Repository navigation
benchmark groups start collapsed, load charts when a group opens - #130
Draft
lwwmanning wants to merge 21 commits into
Draft
lwwmanning wants to merge 21 commits into
lwwmanning wants to merge 21 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
lwwmanning
marked this pull request as ready for review
October 29, 2026 07:23
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
lwwmanning
had a problem deploying
to
bench-preview
October 29, 2026 07:24 — with
GitHub Actions
Error
|
Bench preview for |
lwwmanning
marked this pull request as draft
October 29, 2026 07:30
Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
Each group's summary row now ends with one line that says how Vortex
compares with Parquet, so a folded group still says something. A pure
function, groupHeadline in lib/headline.ts, reads the summary the group
already carries. It adds no query and changes no summary math.
A slower result reads in words ("4.0× slower"), not only through color.
Tone colors wait for the visual redesign. When the needed series are
missing, unmeasured or degenerate, the row shows no headline rather than
a misleading number.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Will Manning <[email protected]>
Each group's summary card and a new client GroupBody now render inside the group's <details>. GroupBody server-renders as an empty div and mounts the group toolbar and the chart grid only while the disclosure is open; closing unmounts them and aborts the group's bundle. A folded landing page therefore ships no chart markup and hydrates no chart island. The loading machinery in lib/chart-store does not change. lib/group-bodies.ts seeds a group's URL series overrides once per page load, so a reopen keeps the user's changes, and lets later code wait until the open groups' bodies have mounted and their bundles settled. chartPriority names the page-wide load priority the islands already used. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
The landing page's fragment now lists the open groups' anchors in page order (#tpc-h-nvme-sf-1,clickbench). An inline script after the last group opens them before the first paint. LandingState writes the fragment on every toggle with replaceState, opens the listed groups after a client navigation or a hashchange, and scrolls to the first one once its body mounts. Expand All and Collapse All write once. The group nav adds its group to the open set. A permalink copies a link to its one group and no longer rewrites the address bar; it shows "copied" only after the clipboard accepts the write. Old single-anchor and opaque-slug links still open their group. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
groupBodiesReady kept a closed group noted, so after an open and a close its `mounted` resolved at once and a waiter could keep the old, aborted bundle. GroupBody now withdraws its note when it closes or unmounts (noteGroupBodyClosed, from the noting effect's cleanup), so a wait that starts later holds for the next mount and that mount's bundle. A wait that already saw the body keeps its bundle. The cleanup never aborts, so a StrictMode replay stays safe. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
The pre-paint script compared every fragment token with every group section, reading `data-group-slug` for each miss, so a crafted multi-megabyte fragment could stall the first paint. It now builds an anchor lookup and a slug lookup once (first section per key, keys prefixed so `__proto__` or `constructor` never reach Object.prototype), skips repeated decoded tokens, and opens what it finds. Behavior is unchanged: the parity test against the lib/open-groups helpers still passes, now with prototype-named tokens too. New tests load 100k-token fragments and bound the script's DOM calls by the number of sections. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
An open group's cards mount only after hydration, so the browser's own scroll restoration lands against a shorter page. The landing page now sets history.scrollRestoration to 'manual' while mounted (and puts the old mode back on unmount) and restores the scroll itself (lib/scroll-restore.ts): - On pagehide, and when a chart link is clicked, it saves to sessionStorage, keyed by path and fragment, the first chart card in view below the sticky header (or else the first group section) and its offset from the viewport top. Storage that is blocked or full never throws. - On mount, planScroll chooses. A reload or Back/Forward with a saved position restores it: once the open bodies mount, and again one frame after their bundles settle. Wheel, touch, key or pointer input stops it. If the element is gone, it falls back to the fragment scroll. A fresh visit, or nothing saved, scrolls to the first listed group as before. A hashchange now also rewrites the fragment to the whole open set (a group already open fires no toggle) and ends a pending restore. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
navigationKind read the document's navigation entry, but the chart page's logo link renders `/` inside the chart page's document. After a reload or a Back to that chart page, the landing page saw 'reload' or 'back_forward' and restored an old position on what was a fresh visit. An entry now counts only when its address has the current path; another path, no address or one that does not parse reads as 'navigate'. Leaving the page before a restore applies no longer overwrites the good save with the top of the page. restoreScroll takes an optional onPendingEnd, called once when its first pass applies, it falls back, or it stops first. Until then pagehide saves the position being restored (saveScroll takes an optional position). Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
The islands now mount into an open group and unmount on close, so teardown runs through effect cleanup and destroy(), not the toggle event. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
Safari throws on a document's 101st history.replaceState call in 10 seconds. Each group toggle made two calls: ours, then Next.js's own re-sync, which is not caught. About 50 fast toggles replaced the landing page with Next.js's error page. A toggle after 300 ms of quiet still writes at once. Inside that time the write waits until the toggles stop, so a burst is two writes and writes stay at least 300 ms apart. A hashchange drops a pending write before it reads the new fragment, and unmount drops it too. A chart link click makes a pending write before it saves the scroll. pagehide saves the scroll under the current URL, which a reload loads, then makes the write and saves again under the new fragment for Back. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
A query or random-access headline now says "(partial)" when it leaves out an engine, or a hot or cold side, that ran Parquet but not Vortex. Before, that result was dropped without a word. An engine that ran only Vortex is still left out silently. A size reads as a multiple outside half to twice Parquet's: "2.0× larger" once the printed percentage would reach 100 (from 1.995), and "2.0× smaller" from a ratio of 0.5 down. No size reads "100% larger" or "100% smaller" any more. Tests now also cover random access with no Parquet run, an unknown engine's label and order, a vector-search tie and NaN score, and the 9.95× and 20× display boundaries. None of the 23 groups on the local production dump changes its wording. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
Before hydration, a reader can already open or close groups, and scroll. LandingState overrode both: - On mount it reopened every group the fragment lists, so a group the reader closed before hydration opened again. A group opened before hydration reached the fragment only with the next toggle. - A Reload or Back restore moved a reader who had already scrolled. The pre-paint script now leaves a marker on its document, after it opens the groups. One-shot passive capture listeners (wheel, touchstart, keydown, pointerdown) set its input flag. A scroll does not set it, so the browser's jump to a single-anchor fragment is not input. LandingState takes the marker on its first mount, once per document. It then opens nothing, writes the fragment once from what is open, and skips a restore when the flag is set, as input after mount would. A client navigation to / finds no marker and opens the groups from the fragment, as before. Also: - Save the scroll position when the tab goes hidden too, through the pagehide path. A mobile browser can discard a hidden tab without a pagehide. - A scroll that no click asked for (a fresh visit, a restore's fallback, a new fragment) now jumps. Only the group nav scrolls smoothly. - Space fragment writes on performance.now(), not Date.now(). A wall clock that jumps forward let two writes come closer than 300 ms. - Drop a pending fragment write when the path changed since it was scheduled, as when the fragment changed. - Remove the wall-clock limit from the bootstrap's linear-work test. The DOM-call counts are the bound. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
A group with no charts mounts no chart island, so it has no bundle to wait for. Its body now requests nothing on open, and the scroll restorer's wait for it resolves at once. Rename a GroupBody test that claimed to pin the once-per-page-load seed of the URL's series overrides. The body stays mounted across a close, so the test passes without that guard; lib/group-bodies.test.ts pins it. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
With JavaScript off, / shows only the loading card: the groups stream inside the Suspense boundary's hidden segment, which only React's inline script reveals. This predates the folded page. Comments in GroupSection, SummaryCard and GroupPermalink claimed behavior "with or without JavaScript". They now say what holds: before hydration, with JavaScript on. page.tsx says why its <noscript> hint never shows in a browser. The hint stays where it is: outside the boundary it would need a wrapper and would sit outside the page layout, above the header or below the footer. performance.md's folded-page section now: - names OpenGroupsScript and the pre-hydration marker; - says why first contentful paint rose 124 -> 184 ms: the previous build first paints its loading card, which the new page no longer needs; - says what the reader sees on Reload and Back (1-2 frames of the page top) and where the 1.4-1.8 layout-instability score comes from; - gives the conditions: local dump, no network throttling, CPU 4x, median of 5 runs (Expand All: 3), one-off scripts, and the previous build (the claude/bench-cleanup head, b4caf7c); - says Expand All mounts its islands in the toggle tasks after the click. Chart.tsx's header adds GroupBody's mount at hydration for a group that is already open. Header.tsx no longer says Expand All writes the fragment once; writes are scheduled and coalesced. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
Input before hydration means the reader has taken over the scroll. The pre-paint script's input flag stopped only the Reload and Back restore. On a fresh visit to a link that lists groups, the page still jumped to the first listed group after hydration, away from where the reader had scrolled. planScroll now returns "none" whenever the flag is set: no restore, no fallback, and no fragment scroll. A scroll alone is still not input, so the browser's jump to a single-anchor fragment changes nothing. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
The design and plan documents for the folded landing page were working notes. The code, bench/docs/architecture/performance.md and the PR record what they decided. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
The first run of LandingState's effect may rewrite the fragment, which keys the saved position and orders the listed groups. Keep that run's reads in a ref so the replay in development restores the same position. Name a click as input before hydration in the comments that list it. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
CodeQL flags the tag-stripping regex as incomplete HTML sanitization. The tests now take the summary row's textContent instead. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
A collapsed group showed only its header row. The summary card now sits after the group's <details>, inside its section, so it shows whether the group is open or not. The toolbar and charts still mount only when the group opens. The card was already in the HTML, so the page ships the same bytes. Comments and docs now say "collapsed", not "folded". Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Will Manning <[email protected]>
lwwmanning
force-pushed
the
claude/bench-landing
branch
from
October 29, 2026 19:33
7ee508e to
511c316
Compare
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Benchmark groups on the landing page start collapsed. Each group shows a one-line result from its summary, for example "DuckDB 2.5× faster". If Vortex is slower, the text says "N× slower". A group loads its charts only when it opens. The URL fragment lists the open groups, and a link with that fragment opens them. Reload and Back open the same groups and go back to the same scroll position.
These values are from a copy of the production database, with the CPU 4× slower:
The APIs do not change. The landing page screenshots change, as expected. With JavaScript off, the page shows only a loading message, as before.
🤖 Generated with Claude Code