Skip to content

Commit b9d2f55

Browse files
committed
fix(benchmarks-website): preserve visible center on chart scope change
The toolbar slider's `applyScope` always called `visibleRange` which unconditionally returned the right-anchored window `[maxIdx - (scope - 1), maxIdx]`. So any scope change while the user had pan-scrolled to inspect a historical window snapped the chart back to the most-recent commits — losing whatever they were looking at. Pass the chart's current `chart.options.scales.x.{min, max}` into `visibleRange` so it can preserve the visible CENTER when the chart is already panned away from the right edge. When the chart is at the right edge or already covers everything, the right-anchor behavior is preserved — that is still the right default at first load and after "show all". Pan/zoom callbacks are unchanged: they go through `rebuildVisibleAndUpdate` directly, not `applyScope`. Bump `STATIC_ASSET_VERSION` to `bench-v3-ui-17` so cached browsers pick up the new JS, and refresh the snapshot tests that reference the versioned asset URLs. Signed-off-by: Claude <noreply@anthropic.com>
1 parent be65b51 commit b9d2f55

5 files changed

Lines changed: 39 additions & 7 deletions

File tree

benchmarks-website/server/src/html.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ const CHART_INIT_JS: &[u8] = include_bytes!("../static/chart-init.js");
8080
const STYLE_CSS: &[u8] = include_bytes!("../static/style.css");
8181
const VORTEX_BLACK_SVG: &[u8] = include_bytes!("../../public/vortex_black_nobg.svg");
8282
const VORTEX_WHITE_SVG: &[u8] = include_bytes!("../../public/vortex_white_nobg.svg");
83-
const STATIC_ASSET_VERSION: &str = "bench-v3-ui-16";
83+
const STATIC_ASSET_VERSION: &str = "bench-v3-ui-17";
8484

8585
/// Commits to inline for the first group's pre-fetched chart payloads.
8686
/// The chart's initial visible window is ~100 commits; bigger windows

benchmarks-website/server/static/chart-init.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,13 +1165,40 @@
11651165
// -----------------------------------------------------------------------
11661166
// Recompute helpers driven by the per-chart toolbar.
11671167
// -----------------------------------------------------------------------
1168-
function visibleRange(commitCount, scope) {
1168+
// Invariant: when `currentRange` is supplied AND the chart is already
1169+
// panned away from the right edge, a scope change preserves the visible
1170+
// CENTER instead of snapping to the most recent N commits. With no
1171+
// `currentRange` (initial render) or a view that already covers
1172+
// everything / sits flush with the newest commit, anchor to the right —
1173+
// the right default at first load and after "show all".
1174+
function visibleRange(commitCount, scope, currentRange) {
11691175
if (commitCount <= 0) return { min: undefined, max: undefined };
11701176
var maxIdx = commitCount - 1;
11711177
if (scope === "all" || !Number.isFinite(scope) || scope <= 0 || scope >= commitCount) {
11721178
return { min: 0, max: maxIdx };
11731179
}
1174-
return { min: Math.max(0, maxIdx - (scope - 1)), max: maxIdx };
1180+
var width = scope;
1181+
var rightAnchored = { min: Math.max(0, maxIdx - (width - 1)), max: maxIdx };
1182+
if (!currentRange) return rightAnchored;
1183+
var curMin = Number.isFinite(currentRange.min) ? currentRange.min : 0;
1184+
var curMax = Number.isFinite(currentRange.max) ? currentRange.max : maxIdx;
1185+
var coversAll = curMin <= 0 && curMax >= maxIdx;
1186+
// Half-commit tolerance: pan/zoom can leave fractional drift even when
1187+
// the user is effectively still flush with the newest commit.
1188+
var atRightEdge = curMax >= maxIdx - 0.5;
1189+
if (coversAll || atRightEdge) return rightAnchored;
1190+
var center = (curMin + curMax) / 2;
1191+
var halfWidth = (width - 1) / 2;
1192+
var newMin = Math.round(center - halfWidth);
1193+
var newMax = newMin + (width - 1);
1194+
if (newMin < 0) {
1195+
newMin = 0;
1196+
newMax = width - 1;
1197+
} else if (newMax > maxIdx) {
1198+
newMax = maxIdx;
1199+
newMin = maxIdx - (width - 1);
1200+
}
1201+
return { min: newMin, max: newMax };
11751202
}
11761203

11771204
function applyScope(card, scopeValue) {
@@ -1181,7 +1208,12 @@
11811208
var commits = chart.data.labels.length;
11821209
var scope = scopeValue === "all" ? "all" : parseInt(scopeValue, 10);
11831210
canvas.__bench_state.scope = scope;
1184-
var range = visibleRange(commits, scope);
1211+
// Capture the chart's existing visible window BEFORE we overwrite it,
1212+
// so `visibleRange` can preserve the center when the user has panned
1213+
// away from the right edge.
1214+
var sx = chart.options.scales.x;
1215+
var currentRange = sx ? { min: sx.min, max: sx.max } : null;
1216+
var range = visibleRange(commits, scope, currentRange);
11851217
chart.options.scales.x.min = range.min;
11861218
chart.options.scales.x.max = range.max;
11871219
rebuildVisibleAndUpdate(card, chart, range.min, range.max);

benchmarks-website/server/tests/snapshots/chart_page_query.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
source: benchmarks-website/server/tests/web_ui.rs
33
expression: body
44
---
5-
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>tpch sf=1 Q1 [nvme] — bench.vortex.dev</title><script>(function(){try{var t=localStorage.getItem("bench-theme");if(t==="light"||t==="dark"){document.documentElement.dataset.theme=t;}}catch(e){}})();</script><link rel="stylesheet" href="/static/style.css?v=bench-v3-ui-16"></head><body><script id="bench-filter-state" type="application/json">{"engines":[],"formats":[]}</script><header class="sticky-header"><div class="header-content"><div class="header-left"><a class="logo-link" href="/" aria-label="bench.vortex.dev home"><img class="site-logo logo-light" src="/vortex_black_nobg.svg?v=bench-v3-ui-16" alt="Vortex"><img class="site-logo logo-dark" src="/vortex_white_nobg.svg?v=bench-v3-ui-16" alt="Vortex"></a><h1 class="site-title">Vortex Benchmarks</h1></div><div class="header-center"><div class="nav-controls" aria-label="Benchmark group controls"><button class="control-btn" type="button" data-action="expand-all"><svg class="btn-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m7 6 5 5 5-5"></path><path d="m7 13 5 5 5-5"></path></svg><span>Expand All</span></button><button class="control-btn" type="button" data-action="collapse-all"><svg class="btn-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m17 18-5-5-5 5"></path><path d="m17 11-5-5-5 5"></path></svg><span>Collapse All</span></button><div class="filter-dropdown" data-role="global-filter-bar"><button class="control-btn filter-trigger" type="button" data-role="filter-trigger" aria-haspopup="true" aria-expanded="false"><svg class="btn-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon></svg><span>Filters</span></button><div class="filter-panel" data-role="filter-panel" hidden><div class="global-filter-row"><span class="global-filter-label">Engine</span><button class="filter-chip filter-chip--all" type="button" data-filter="engine" data-value="*" aria-pressed="false">all</button><button class="filter-chip filter-chip--active" type="button" data-filter="engine" data-value="datafusion" aria-pressed="true">datafusion</button><button class="filter-chip filter-chip--active" type="button" data-filter="engine" data-value="duckdb" aria-pressed="true">duckdb</button></div><div class="global-filter-row"><span class="global-filter-label">Format</span><button class="filter-chip filter-chip--all" type="button" data-filter="format" data-value="*" aria-pressed="false">all</button><button class="filter-chip filter-chip--active" type="button" data-filter="format" data-value="parquet" aria-pressed="true">parquet</button><button class="filter-chip filter-chip--active" type="button" data-filter="format" data-value="vortex-file-compressed" aria-pressed="true">vortex-file-compressed</button></div></div></div></div></div><div class="header-right"><a class="repo-link" href="https://github.com/vortex-data/vortex" rel="noopener noreferrer" target="_blank"><svg class="github-logo" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg><span>GitHub</span></a><button class="control-btn theme-toggle" type="button" data-role="theme-toggle" data-next-theme="light" aria-label="Toggle color theme"><svg class="btn-icon theme-icon theme-icon-light" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg><svg class="btn-icon theme-icon theme-icon-dark" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.99 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 20.99 12.79z"></path></svg><span class="theme-toggle-label">Light</span></button></div></div></header><main><p class="chart-meta">unit: <code>ns</code> · 2 series · 3 commits<span class="chart-badge chart-badge--downsampled" data-role="downsample-badge" hidden></span></p><section class="chart-card" data-chart-index="0" data-chart-slug="qm.eyJrIjoiUXVlcnlNZWFzdXJlbWVudCIsImRhdGFzZXQiOiJ0cGNoIiwiZGF0YXNldF92YXJpYW50IjpudWxsLCJzY2FsZV9mYWN0b3IiOiIxIiwic3RvcmFnZSI6Im52bWUiLCJxdWVyeV9pZHgiOjF9"><div class="toolbar toolbar--card" aria-label="Chart controls"><div class="toolbar-group" role="group" aria-label="Visible commits"><span class="toolbar-label">Show</span><input class="toolbar-slider" id="scope-slider-0" type="range" min="5" max="100" step="1" value="100" data-role="scope-slider" aria-label="Custom commit window"></div><div class="toolbar-group" role="group" aria-label="Y-axis scale"><span class="toolbar-label">Y</span><button class="toolbar-btn toolbar-btn--active" type="button" data-y="linear">linear</button><button class="toolbar-btn" type="button" data-y="log">log</button></div></div><div class="chart-tooltip-host"></div><div class="chart-wrap"><canvas data-chart-index="0"></canvas></div><div class="chart-range-strip" data-chart-index="0" data-role="range-strip" aria-label="Visible commit range" role="slider"><div class="chart-range-strip-track"><div class="chart-range-strip-window" data-role="range-window"><span class="chart-range-strip-handle chart-range-strip-handle--left" data-role="range-handle-left" aria-hidden="true"></span><span class="chart-range-strip-handle chart-range-strip-handle--right" data-role="range-handle-right" aria-hidden="true"></span></div></div></div><script id="chart-data-0" type="application/json">{"display_name":"tpch sf=1 Q1 [nvme]","unit":"ns","commits":[{"sha":"1111111111111111111111111111111111111111","timestamp":"2026-04-23 12:00:00+00","message":"first commit","url":"https://github.com/vortex-data/vortex/commit/1111111111111111111111111111111111111111"},{"sha":"2222222222222222222222222222222222222222","timestamp":"2026-04-24 12:00:00+00","message":"second commit","url":"https://github.com/vortex-data/vortex/commit/2222222222222222222222222222222222222222"},{"sha":"3333333333333333333333333333333333333333","timestamp":"2026-04-25 12:00:00+00","message":"third commit","url":"https://github.com/vortex-data/vortex/commit/3333333333333333333333333333333333333333"}],"series":{"datafusion:vortex-file-compressed":[1000000.0,1050000.0,1100000.0],"duckdb:parquet":[800000.0,850000.0,900000.0]},"series_meta":{"datafusion:vortex-file-compressed":{"engine":"datafusion","format":"vortex-file-compressed"},"duckdb:parquet":{"engine":"duckdb","format":"parquet"}}}</script></section><noscript><p class="no-script">JavaScript is required to render the chart.</p></noscript></main><script src="/static/chart.umd.js?v=bench-v3-ui-16" defer></script><script src="/static/chartjs-plugin-zoom.umd.min.js?v=bench-v3-ui-16" defer></script><script src="/static/chart-init.js?v=bench-v3-ui-16" defer></script></body></html>
5+
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>tpch sf=1 Q1 [nvme] — bench.vortex.dev</title><script>(function(){try{var t=localStorage.getItem("bench-theme");if(t==="light"||t==="dark"){document.documentElement.dataset.theme=t;}}catch(e){}})();</script><link rel="stylesheet" href="/static/style.css?v=bench-v3-ui-17"></head><body><script id="bench-filter-state" type="application/json">{"engines":[],"formats":[]}</script><header class="sticky-header"><div class="header-content"><div class="header-left"><a class="logo-link" href="/" aria-label="bench.vortex.dev home"><img class="site-logo logo-light" src="/vortex_black_nobg.svg?v=bench-v3-ui-17" alt="Vortex"><img class="site-logo logo-dark" src="/vortex_white_nobg.svg?v=bench-v3-ui-17" alt="Vortex"></a><h1 class="site-title">Vortex Benchmarks</h1></div><div class="header-center"><div class="nav-controls" aria-label="Benchmark group controls"><button class="control-btn" type="button" data-action="expand-all"><svg class="btn-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m7 6 5 5 5-5"></path><path d="m7 13 5 5 5-5"></path></svg><span>Expand All</span></button><button class="control-btn" type="button" data-action="collapse-all"><svg class="btn-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m17 18-5-5-5 5"></path><path d="m17 11-5-5-5 5"></path></svg><span>Collapse All</span></button><div class="filter-dropdown" data-role="global-filter-bar"><button class="control-btn filter-trigger" type="button" data-role="filter-trigger" aria-haspopup="true" aria-expanded="false"><svg class="btn-icon" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon></svg><span>Filters</span></button><div class="filter-panel" data-role="filter-panel" hidden><div class="global-filter-row"><span class="global-filter-label">Engine</span><button class="filter-chip filter-chip--all" type="button" data-filter="engine" data-value="*" aria-pressed="false">all</button><button class="filter-chip filter-chip--active" type="button" data-filter="engine" data-value="datafusion" aria-pressed="true">datafusion</button><button class="filter-chip filter-chip--active" type="button" data-filter="engine" data-value="duckdb" aria-pressed="true">duckdb</button></div><div class="global-filter-row"><span class="global-filter-label">Format</span><button class="filter-chip filter-chip--all" type="button" data-filter="format" data-value="*" aria-pressed="false">all</button><button class="filter-chip filter-chip--active" type="button" data-filter="format" data-value="parquet" aria-pressed="true">parquet</button><button class="filter-chip filter-chip--active" type="button" data-filter="format" data-value="vortex-file-compressed" aria-pressed="true">vortex-file-compressed</button></div></div></div></div></div><div class="header-right"><a class="repo-link" href="https://github.com/vortex-data/vortex" rel="noopener noreferrer" target="_blank"><svg class="github-logo" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" aria-hidden="true"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg><span>GitHub</span></a><button class="control-btn theme-toggle" type="button" data-role="theme-toggle" data-next-theme="light" aria-label="Toggle color theme"><svg class="btn-icon theme-icon theme-icon-light" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg><svg class="btn-icon theme-icon theme-icon-dark" viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.99 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 20.99 12.79z"></path></svg><span class="theme-toggle-label">Light</span></button></div></div></header><main><p class="chart-meta">unit: <code>ns</code> · 2 series · 3 commits<span class="chart-badge chart-badge--downsampled" data-role="downsample-badge" hidden></span></p><section class="chart-card" data-chart-index="0" data-chart-slug="qm.eyJrIjoiUXVlcnlNZWFzdXJlbWVudCIsImRhdGFzZXQiOiJ0cGNoIiwiZGF0YXNldF92YXJpYW50IjpudWxsLCJzY2FsZV9mYWN0b3IiOiIxIiwic3RvcmFnZSI6Im52bWUiLCJxdWVyeV9pZHgiOjF9"><div class="toolbar toolbar--card" aria-label="Chart controls"><div class="toolbar-group" role="group" aria-label="Visible commits"><span class="toolbar-label">Show</span><input class="toolbar-slider" id="scope-slider-0" type="range" min="5" max="100" step="1" value="100" data-role="scope-slider" aria-label="Custom commit window"></div><div class="toolbar-group" role="group" aria-label="Y-axis scale"><span class="toolbar-label">Y</span><button class="toolbar-btn toolbar-btn--active" type="button" data-y="linear">linear</button><button class="toolbar-btn" type="button" data-y="log">log</button></div></div><div class="chart-tooltip-host"></div><div class="chart-wrap"><canvas data-chart-index="0"></canvas></div><div class="chart-range-strip" data-chart-index="0" data-role="range-strip" aria-label="Visible commit range" role="slider"><div class="chart-range-strip-track"><div class="chart-range-strip-window" data-role="range-window"><span class="chart-range-strip-handle chart-range-strip-handle--left" data-role="range-handle-left" aria-hidden="true"></span><span class="chart-range-strip-handle chart-range-strip-handle--right" data-role="range-handle-right" aria-hidden="true"></span></div></div></div><script id="chart-data-0" type="application/json">{"display_name":"tpch sf=1 Q1 [nvme]","unit":"ns","commits":[{"sha":"1111111111111111111111111111111111111111","timestamp":"2026-04-23 12:00:00+00","message":"first commit","url":"https://github.com/vortex-data/vortex/commit/1111111111111111111111111111111111111111"},{"sha":"2222222222222222222222222222222222222222","timestamp":"2026-04-24 12:00:00+00","message":"second commit","url":"https://github.com/vortex-data/vortex/commit/2222222222222222222222222222222222222222"},{"sha":"3333333333333333333333333333333333333333","timestamp":"2026-04-25 12:00:00+00","message":"third commit","url":"https://github.com/vortex-data/vortex/commit/3333333333333333333333333333333333333333"}],"series":{"datafusion:vortex-file-compressed":[1000000.0,1050000.0,1100000.0],"duckdb:parquet":[800000.0,850000.0,900000.0]},"series_meta":{"datafusion:vortex-file-compressed":{"engine":"datafusion","format":"vortex-file-compressed"},"duckdb:parquet":{"engine":"duckdb","format":"parquet"}}}</script></section><noscript><p class="no-script">JavaScript is required to render the chart.</p></noscript></main><script src="/static/chart.umd.js?v=bench-v3-ui-17" defer></script><script src="/static/chartjs-plugin-zoom.umd.min.js?v=bench-v3-ui-17" defer></script><script src="/static/chart-init.js?v=bench-v3-ui-17" defer></script></body></html>

0 commit comments

Comments
 (0)