Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 33 additions & 32 deletions docs/state-ownership.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ Depends on: `GlobalFilterProvider` (reads all filter state and availability, inc

- `selectedYAxisMetric` (`i_metric`), `selectedXAxisMetric` (`i_xmetric`), `selectedE2eXAxisMetric` (`i_e2e_xmetric`)
- `scaleType` — `auto | linear | log` (`i_scale`)
- `hideNonOptimal` (`i_optimal`), `hidePointLabels` (`i_nolabel`), `logScale` (`i_log`)
- `hideNonOptimal` (`i_optimal`), `showPointLabels` (`i_label`), `logScale` (`i_log`)
- `highContrast` (`i_hc`), `isLegendExpanded` (`i_legend`)
- `useAdvancedLabels` (`i_advlabel`), `showGradientLabels` (`i_gradlabel`)
- `colorShuffleSeed` — no URL param; ephemeral
Expand Down Expand Up @@ -260,34 +260,35 @@ Historical Trends and TCO Calculator share the inference tab's URL path (`/infer

### Full parameter list

| Param | Owner | Default |
| --------------- | ------------------- | -------------------------------- |
| `g_model` | GlobalFilterContext | `DeepSeek-R1-0528` |
| `g_rundate` | GlobalFilterContext | `''` |
| `g_runid` | GlobalFilterContext | `''` |
| `i_seq` | GlobalFilterContext | `8k/1k` |
| `i_prec` | GlobalFilterContext | `fp4` |
| `i_metric` | InferenceProvider | `y_tpPerGpu` |
| `i_xmetric` | InferenceProvider | `p99_ttft` |
| `i_e2e_xmetric` | InferenceProvider | `''` |
| `i_scale` | InferenceProvider | `auto` |
| `i_gpus` | InferenceProvider | `''` |
| `i_dates` | InferenceProvider | `''` |
| `i_dstart` | InferenceProvider | `''` |
| `i_dend` | InferenceProvider | `''` |
| `i_optimal` | InferenceProvider | `''` (truthy = hide non-optimal) |
| `i_nolabel` | InferenceProvider | `''` |
| `i_hc` | InferenceProvider | `''` |
| `i_log` | InferenceProvider | `''` |
| `i_legend` | InferenceProvider | `''` |
| `i_advlabel` | InferenceProvider | `''` |
| `i_gradlabel` | InferenceProvider | `''` |
| `e_rundate` | EvaluationProvider | `''` |
| `e_bench` | EvaluationProvider | `''` |
| `e_hc` | EvaluationProvider | `''` |
| `e_labels` | EvaluationProvider | `''` |
| `e_legend` | EvaluationProvider | `''` |
| `r_range` | ReliabilityProvider | `last-3-months` |
| `r_pct` | ReliabilityProvider | `''` |
| `r_hc` | ReliabilityProvider | `''` |
| `r_legend` | ReliabilityProvider | `''` |
| Param | Owner | Default |
| --------------- | ------------------- | --------------------------------- |
| `g_model` | GlobalFilterContext | `DeepSeek-R1-0528` |
| `g_rundate` | GlobalFilterContext | `''` |
| `g_runid` | GlobalFilterContext | `''` |
| `i_seq` | GlobalFilterContext | `8k/1k` |
| `i_prec` | GlobalFilterContext | `fp4` |
| `i_metric` | InferenceProvider | `y_tpPerGpu` |
| `i_xmetric` | InferenceProvider | `p99_ttft` |
| `i_e2e_xmetric` | InferenceProvider | `''` |
| `i_scale` | InferenceProvider | `auto` |
| `i_gpus` | InferenceProvider | `''` |
| `i_dates` | InferenceProvider | `''` |
| `i_dstart` | InferenceProvider | `''` |
| `i_dend` | InferenceProvider | `''` |
| `i_optimal` | InferenceProvider | `''` (truthy = hide non-optimal) |
| `i_label` | InferenceProvider | `''` (truthy = show point labels) |
| `i_nolabel` | InferenceProvider | `''` (legacy, read-only) |
| `i_hc` | InferenceProvider | `''` |
| `i_log` | InferenceProvider | `''` |
| `i_legend` | InferenceProvider | `''` |
| `i_advlabel` | InferenceProvider | `''` |
| `i_gradlabel` | InferenceProvider | `''` |
| `e_rundate` | EvaluationProvider | `''` |
| `e_bench` | EvaluationProvider | `''` |
| `e_hc` | EvaluationProvider | `''` |
| `e_labels` | EvaluationProvider | `''` |
| `e_legend` | EvaluationProvider | `''` |
| `r_range` | ReliabilityProvider | `last-3-months` |
| `r_pct` | ReliabilityProvider | `''` |
| `r_hc` | ReliabilityProvider | `''` |
| `r_legend` | ReliabilityProvider | `''` |
64 changes: 59 additions & 5 deletions packages/app/cypress/e2e/line-labels.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,22 @@ describe('Line Labels Toggle', () => {
cy.get('label[for="scatter-line-labels"]').should('contain.text', 'Line Labels');
});

it('Line Labels toggle is off by default', () => {
cy.get('#scatter-line-labels').should('have.attr', 'data-state', 'unchecked');
it('Line Labels toggle is on by default', () => {
cy.get('#scatter-line-labels').should('have.attr', 'data-state', 'checked');

// Line labels render without any interaction
cy.get('[data-testid="scatter-graph"] svg g.line-label').should('have.length.greaterThan', 0);
});

it('toggling Line Labels on renders label elements on the chart', () => {
it('toggling Line Labels off then back on removes and restores label elements', () => {
// On by default — turn it off first.
cy.get('#scatter-line-labels').click();
cy.get('#scatter-line-labels').should('have.attr', 'data-state', 'checked');
cy.get('#scatter-line-labels').should('have.attr', 'data-state', 'unchecked');
cy.get('[data-testid="scatter-graph"] svg g.line-label').should('have.length', 0);

// Line label groups should appear in the SVG
// Turn it back on — labels return.
cy.get('#scatter-line-labels').click();
cy.get('#scatter-line-labels').should('have.attr', 'data-state', 'checked');
cy.get('[data-testid="scatter-graph"] svg g.line-label').should('have.length.greaterThan', 0);
});

Expand Down Expand Up @@ -148,6 +155,53 @@ describe('Line Labels Toggle', () => {
cy.get('[data-testid="scatter-graph"] svg g.line-label').should('have.length.greaterThan', 0);
});

it('URL param i_linelabel=0 disables line labels on load', () => {
cy.visit('/inference?i_linelabel=0', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
});
cy.get('[data-testid="scatter-graph"]').should('be.visible');
cy.get('#scatter-line-labels').should('have.attr', 'data-state', 'unchecked');

// Labels should not be rendered
cy.get('[data-testid="scatter-graph"] svg g.line-label').should('have.length', 0);
});

it('legacy URL param i_nolabel=1 keeps point labels hidden on load', () => {
cy.visit('/inference?i_nolabel=1', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
});
cy.get('[data-testid="scatter-graph"]').should('be.visible');
cy.get('#scatter-point-labels').should('have.attr', 'data-state', 'unchecked');
});

it('legacy URL param i_advlabel=1 auto-enables Labels so advanced labels render', () => {
cy.visit('/inference?i_advlabel=1', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
});
cy.get('[data-testid="scatter-graph"]').should('be.visible');
cy.get('#scatter-parallelism-labels').should('have.attr', 'data-state', 'checked');
// Labels toggle is auto-enabled by the URL hydration so the advanced
// (parallelism) point labels actually render.
cy.get('#scatter-point-labels').should('have.attr', 'data-state', 'checked');
});

it('legacy URL combo i_advlabel=1&i_nolabel=1 keeps point labels hidden (i_nolabel wins)', () => {
cy.visit('/inference?i_advlabel=1&i_nolabel=1', {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
},
});
cy.get('[data-testid="scatter-graph"]').should('be.visible');
cy.get('#scatter-parallelism-labels').should('have.attr', 'data-state', 'checked');
cy.get('#scatter-point-labels').should('have.attr', 'data-state', 'unchecked');
});

it('appends the precision to each line label when multiple precisions are selected', () => {
// Pair the FP4+FP8 selection with a model that has both precisions in the
// fixtures. The default model (DeepSeek-V4-Pro) only has FP4, so
Expand Down
4 changes: 2 additions & 2 deletions packages/app/cypress/support/mock-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,8 @@ export function createMockInferenceContext(
setIsLegendExpanded: namedStub('setIsLegendExpanded'),
hideNonOptimal: false,
setHideNonOptimal: namedStub('setHideNonOptimal'),
hidePointLabels: false,
setHidePointLabels: namedStub('setHidePointLabels'),
showPointLabels: false,
setShowPointLabels: namedStub('setShowPointLabels'),
highContrast: false,
setHighContrast: namedStub('setHighContrast'),
logScale: false,
Expand Down
26 changes: 18 additions & 8 deletions packages/app/src/components/inference/InferenceContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,15 +157,25 @@ export function InferenceProvider({
});

const [hideNonOptimal, setHideNonOptimal] = useState(() => getUrlParam('i_optimal') !== '0');
const [hidePointLabels, setHidePointLabels] = useState(() => getUrlParam('i_nolabel') === '1');
const [showPointLabels, setShowPointLabels] = useState(() => {
// Legacy `?i_nolabel=1` from before the rename: keep hiding point labels
// explicitly so the share link's intent survives future default changes.
if (getUrlParam('i_nolabel') === '1') return false;
if (getUrlParam('i_label') === '1') return true;
// Old share links set `?i_advlabel=1` while keeping the labels default
// (shown). Mirror the toggle's auto-enable side-effect on load so those
// links still render advanced labels under the new default-off behavior.
if (getUrlParam('i_advlabel') === '1') return true;
return false;
});
const [logScale, setLogScale] = useState(() => getUrlParam('i_log') === '1');
const [useAdvancedLabels, setUseAdvancedLabels] = useState(
() => getUrlParam('i_advlabel') === '1',
);
const [showGradientLabels, setShowGradientLabels] = useState(
() => getUrlParam('i_gradlabel') === '1',
);
const [showLineLabels, setShowLineLabels] = useState(() => getUrlParam('i_linelabel') === '1');
const [showLineLabels, setShowLineLabels] = useState(() => getUrlParam('i_linelabel') !== '0');
const [showSpeedOverlay, setShowSpeedOverlay] = useState(() => getUrlParam('i_speed') === '1');
const [showMinecraftOverlay, setShowMinecraftOverlay] = useState(
() => getUrlParam('i_mc') === '1',
Expand Down Expand Up @@ -821,7 +831,7 @@ export function InferenceProvider({
i_dstart: selectedDateRange.startDate,
i_dend: selectedDateRange.endDate,
i_optimal: hideNonOptimal ? '' : '0',
i_nolabel: hidePointLabels ? '1' : '',
i_label: showPointLabels ? '1' : '',
i_hc: highContrast ? '1' : '',
i_log: logScale ? '1' : '',
i_xmetric: selectedXAxisMetric || '',
Expand All @@ -830,7 +840,7 @@ export function InferenceProvider({
i_legend: isLegendExpanded ? '' : '0',
i_advlabel: useAdvancedLabels ? '1' : '',
i_gradlabel: showGradientLabels ? '1' : '',
i_linelabel: showLineLabels ? '1' : '',
i_linelabel: showLineLabels ? '' : '0',
i_speed: showSpeedOverlay ? '1' : '',
i_mc: showMinecraftOverlay ? '1' : '',
i_active: iActiveStr,
Expand All @@ -844,7 +854,7 @@ export function InferenceProvider({
selectedDates,
selectedDateRange,
hideNonOptimal,
hidePointLabels,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legacy i_nolabel poisons share URLs

Medium Severity

After opening a link with legacy i_nolabel=1, turning point labels on writes i_label=1 but leaves the original i_nolabel=1 in share state. Hydration checks i_nolabel before i_label, so re-shared or reloaded links keep labels hidden despite the user enabling them.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9c5ea62. Configure here.

showPointLabels,
highContrast,
logScale,
isLegendExpanded,
Expand Down Expand Up @@ -989,8 +999,8 @@ export function InferenceProvider({
setIsLegendExpanded,
hideNonOptimal,
setHideNonOptimal,
hidePointLabels,
setHidePointLabels,
showPointLabels,
setShowPointLabels,
highContrast,
setHighContrast,
logScale,
Expand Down Expand Up @@ -1089,7 +1099,7 @@ export function InferenceProvider({
availableSequences,
availableModels,
hideNonOptimal,
hidePointLabels,
showPointLabels,
highContrast,
logScale,
isLegendExpanded,
Expand Down
4 changes: 2 additions & 2 deletions packages/app/src/components/inference/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -645,8 +645,8 @@ export interface InferenceChartContextType {
isLegendExpanded: boolean;
hideNonOptimal: boolean;
setHideNonOptimal: (hide: boolean) => void;
hidePointLabels: boolean;
setHidePointLabels: (hide: boolean) => void;
showPointLabels: boolean;
setShowPointLabels: (show: boolean) => void;
highContrast: boolean;
setHighContrast: (highContrast: boolean) => void;
logScale: boolean;
Expand Down
19 changes: 11 additions & 8 deletions packages/app/src/components/inference/ui/GPUGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,8 @@ const GPUGraph = React.memo(
activeDates,
hideNonOptimal,
setHideNonOptimal,
hidePointLabels,
setHidePointLabels,
showPointLabels,
setShowPointLabels,
logScale,
setLogScale,
isLegendExpanded,
Expand Down Expand Up @@ -754,7 +754,7 @@ const GPUGraph = React.memo(
data: filteredData,
config: {
getColor,
hideLabels: hidePointLabels,
hideLabels: !showPointLabels,
getLabelText: (d) => (useAdvancedLabels ? getPointLabel(d) : String(d.tp)),
foreground: 'var(--foreground)',
dataAttrs: {
Expand Down Expand Up @@ -876,12 +876,12 @@ const GPUGraph = React.memo(
},
},
{
id: 'gpu-hide-point-labels',
label: 'Hide Labels',
checked: hidePointLabels,
id: 'gpu-point-labels',
label: 'Labels',
checked: showPointLabels,
onCheckedChange: (c) => {
setHidePointLabels(c);
track('interactivity_hide_point_labels_toggled', { enabled: c });
setShowPointLabels(c);
track('interactivity_point_labels_toggled', { enabled: c });
},
},
{
Expand All @@ -891,6 +891,9 @@ const GPUGraph = React.memo(
onCheckedChange: (c) => {
setUseAdvancedLabels(c);
track('interactivity_advanced_labels_toggled', { enabled: c });
// Parallelism labels are point labels; turning them on is
// pointless if labels are hidden, so auto-enable Labels.
if (c && !showPointLabels) setShowPointLabels(true);
},
},
{
Expand Down
23 changes: 13 additions & 10 deletions packages/app/src/components/inference/ui/ScatterGraph.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ const ScatterGraph = React.memo(
selectedRunId,
hideNonOptimal,
setHideNonOptimal,
hidePointLabels,
setHidePointLabels,
showPointLabels,
setShowPointLabels,
selectAllHwTypes,
highContrast,
setHighContrast,
Expand Down Expand Up @@ -1486,7 +1486,7 @@ const ScatterGraph = React.memo(
getCssColor(resolveColor(d.hwKey as string)),
getOpacity: (d) => (isPointVisible(d) ? 1 : 0),
getPointerEvents: (d) => (isPointVisible(d) ? 'auto' : 'none'),
hideLabels: hidePointLabels || showGradientLabels,
hideLabels: !showPointLabels || showGradientLabels,
getLabelText: (d) => (useAdvancedLabels ? getPointLabel(d) : String(d.tp)),
foreground: 'var(--foreground)',
dataAttrs: {
Expand Down Expand Up @@ -1585,7 +1585,7 @@ const ScatterGraph = React.memo(
);

// Labels
const showLabels = !hidePointLabels && !showGradientLabels;
const showLabels = showPointLabels && !showGradientLabels;
overlayPoints.each(function (d) {
d3.select(this)
.selectAll<SVGTextElement, boolean>('.overlay-label')
Expand Down Expand Up @@ -1864,7 +1864,7 @@ const ScatterGraph = React.memo(
resolveColor,
pointsData,
isPointVisible,
hidePointLabels,
showPointLabels,
useAdvancedLabels,
buildPointConfigId,
overlayData,
Expand Down Expand Up @@ -2154,12 +2154,12 @@ const ScatterGraph = React.memo(
},
},
{
id: 'scatter-hide-point-labels',
label: 'Hide Labels',
checked: hidePointLabels,
id: 'scatter-point-labels',
label: 'Labels',
checked: showPointLabels,
onCheckedChange: (checked: boolean) => {
setHidePointLabels(checked);
track('latency_hide_point_labels_toggled', { enabled: checked });
setShowPointLabels(checked);
track('latency_point_labels_toggled', { enabled: checked });
},
},
{
Expand All @@ -2178,6 +2178,9 @@ const ScatterGraph = React.memo(
onCheckedChange: (checked: boolean) => {
setUseAdvancedLabels(checked);
track('latency_advanced_labels_toggled', { enabled: checked });
// Parallelism labels are point labels; turning them on is
// pointless if labels are hidden, so auto-enable Labels.
if (checked && !showPointLabels) setShowPointLabels(true);
if (checked && !showGradientLabels) {
window.dispatchEvent(
new CustomEvent(GRADIENT_NUDGE_EVENT, {
Expand Down
5 changes: 5 additions & 0 deletions packages/app/src/lib/url-state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ const URL_STATE_KEYS = [
'i_dstart',
'i_dend',
'i_optimal',
'i_label',
// Legacy alias of `i_label` with inverted semantics — read-only on load so
// pre-rename share links (?i_nolabel=1) keep hiding point labels even if the
// default flips again later. New code only writes `i_label`.
'i_nolabel',
'i_hc',
'i_log',
Expand Down Expand Up @@ -77,6 +81,7 @@ export const PARAM_DEFAULTS: Record<UrlStateKey, string> = {
i_dstart: '',
i_dend: '',
i_optimal: '',
i_label: '',
i_nolabel: '',
i_hc: '',
i_log: '',
Expand Down
Loading