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
163 changes: 163 additions & 0 deletions packages/app/cypress/e2e/overlay-optimal-only.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/**
* Overlay (unofficial run) points must respect the "Optimal Only" toggle the
* same way official points do.
*
* Regression: with Optimal Only ON, official non-pareto points are hidden via
* `isPointVisible`, but overlay X markers rendered every point unconditionally.
* On the agentic interactivity chart this made an e2e-dominated config (TP8
* C=4 in the GLM5.2 B300 hicache run) look like a pareto point: its X marker
* stayed visible sitting on the dashed roofline (the monotone spline between
* C=8 and C=2 passes within ~0.5% of it) while the official twin was hidden.
*
* Fixture values are the real run-29682242847 numbers:
* conc, p90_intvty, tput_per_gpu, p90_e2el
* C=4 is dominated on e2e by C=8 (12874 tok/s @ 33.1s vs 9415 @ 48.0s), so
* with Optimal Only ON exactly 4 of the 5 overlay X's must stay visible.
*/
import { unlockAgenticGate } from '../support/e2e';

const DEFAULT_MODEL_DB_KEY = 'dsv4';
const AGENTIC_DATE = '2026-07-19';
const OVERLAY_RUN_ID = '29682242847';
const OVERLAY_RUN_URL = `https://github.com/SemiAnalysisAI/InferenceX/actions/runs/${OVERLAY_RUN_ID}`;

const REAL_CONFIGS: [number, number, number, number][] = [
[48, 10.6, 17199, 126.9],
[8, 68.5, 12874, 33.1],
[4, 88.3, 9415, 48], // e2e-dominated by C=8 → NOT optimal
[2, 111.1, 5018, 30],
[1, 130.2, 2600, 25.8],
];

const metricsFor = (intvty: number, tput: number, e2el: number): Record<string, number> => ({
median_itl: 1 / (intvty * 1.2),
p90_itl: 1 / intvty,
p99_itl: 1 / (intvty * 0.8),
median_e2el: e2el * 0.8,
p90_e2el: e2el,
p99_e2el: e2el * 1.3,
median_ttft: 0.5,
p90_ttft: 1,
p99_ttft: 2,
tput_per_gpu: tput,
output_tput_per_gpu: tput * 0.3,
input_tput_per_gpu: tput * 0.7,
});

let idCursor = 900000;
const b300Rows = (runUrl: string | null) =>
REAL_CONFIGS.map(([conc, intvty, tput, e2el]) => ({
id: runUrl ? 0 : idCursor++,
hardware: 'b300',
framework: 'sglang',
model: DEFAULT_MODEL_DB_KEY,
precision: 'fp4',
spec_method: 'none',
disagg: false,
is_multinode: false,
prefill_tp: 8,
decode_tp: 8,
num_prefill_gpu: 8,
num_decode_gpu: 8,
isl: null,
osl: null,
conc,
offload_mode: 'on',
benchmark_type: 'agentic_traces',
image: 'sglang:test',
metrics: metricsFor(intvty, tput, e2el),
workers: null,
date: AGENTIC_DATE,
run_url: runUrl,
}));

const availability = [
{
model: DEFAULT_MODEL_DB_KEY,
isl: null,
osl: null,
precision: 'fp4',
hardware: 'b300',
framework: 'sglang',
spec_method: 'none',
disagg: false,
benchmark_type: 'agentic_traces',
date: AGENTIC_DATE,
},
];

const countVisible = ($els: JQuery<HTMLElement>): number =>
[...$els].filter((el) => getComputedStyle(el).opacity !== '0').length;

describe('Overlay points respect Optimal Only (agentic interactivity)', () => {
before(() => {
cy.intercept('GET', '/api/v1/availability', { body: availability }).as('availability');
cy.intercept('GET', '/api/v1/benchmarks*', { body: b300Rows(null) }).as('benchmarks');
cy.intercept('GET', '/api/unofficial-run*', {
body: {
runInfos: [
{
id: OVERLAY_RUN_ID,
name: 'add-glm5.2-b300-agentic-hicache',
branch: 'add-glm5.2-b300-agentic-hicache',
sha: 'abc000',
createdAt: `${AGENTIC_DATE}T00:00:00Z`,
url: OVERLAY_RUN_URL,
conclusion: 'success',
status: 'completed',
isNonMainBranch: true,
},
],
benchmarks: b300Rows(OVERLAY_RUN_URL),
evaluations: [],
},
}).as('unofficialRun');
cy.visit(`/inference?unofficialrun=${OVERLAY_RUN_ID}&i_seq=agentic-traces&i_pctl=p90`, {
onBeforeLoad(win) {
win.localStorage.setItem('inferencex-star-modal-dismissed', String(Date.now()));
unlockAgenticGate(win);
},
});
cy.wait('@unofficialRun');
cy.get('[data-testid="chart-figure"]').should('have.length.at.least', 1);
cy.get('[data-testid="x-axis-mode-interactivity"]').should(
'have.attr',
'aria-selected',
'true',
);
cy.get('[data-testid="inference-chart-display"] svg .unofficial-overlay-pt').should(
'have.length',
REAL_CONFIGS.length,
);
});

// Optimal Only defaults ON (i_optimal !== '0') — the DEFAULT view is where
// the regression lived: official C=4 hidden, overlay C=4 X still drawn.
it('hides the e2e-dominated overlay point in the default Optimal Only view', () => {
cy.get('#scatter-hide-non-optimal').should('have.attr', 'data-state', 'checked');
// Official parity check: 4 of 5 official dots visible.
cy.get('[data-testid="inference-chart-display"] svg .dot-group').then(($dots) => {
expect(countVisible($dots), 'visible official points').to.eq(REAL_CONFIGS.length - 1);
});
// The overlay must hide its C=4 too — 4 of 5 X markers visible.
cy.get('[data-testid="inference-chart-display"] svg .unofficial-overlay-pt').then(($pts) => {
expect(countVisible($pts), 'visible overlay X markers').to.eq(REAL_CONFIGS.length - 1);
});
});

it('shows all overlay points when Optimal Only is turned off', () => {
cy.get('#scatter-hide-non-optimal').click();
cy.get('#scatter-hide-non-optimal').should('have.attr', 'data-state', 'unchecked');
cy.get('[data-testid="inference-chart-display"] svg .unofficial-overlay-pt').then(($pts) => {
expect(countVisible($pts), 'visible overlay X markers').to.eq(REAL_CONFIGS.length);
});
});

it('re-hides the e2e-dominated overlay point when Optimal Only is re-enabled', () => {
cy.get('#scatter-hide-non-optimal').click();
cy.get('#scatter-hide-non-optimal').should('have.attr', 'data-state', 'checked');
cy.get('[data-testid="inference-chart-display"] svg .unofficial-overlay-pt').then(($pts) => {
expect(countVisible($pts), 'visible overlay X markers').to.eq(REAL_CONFIGS.length - 1);
});
});
});
120 changes: 30 additions & 90 deletions packages/app/src/components/inference/hooks/useChartData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,12 @@ import {
getModelSortIndex,
hardwareKeyMatchesAnyBase,
} from '@/lib/constants';
import {
mergeRunScopedRows,
transformBenchmarkRows,
withPercentile,
} from '@/lib/benchmark-transform';
import { mergeRunScopedRows, transformBenchmarkRows } from '@/lib/benchmark-transform';
import { Sequence, type Model } from '@/lib/data-mappings';
import { isPersistedBenchmarkId } from '@/lib/benchmark-id';
import { calculateCostsForGpus, calculatePowerForGpus } from '@/lib/utils';
import { paretoFrontForDirection, type ParetoDirection } from '@/lib/chart-utils';
import { e2eFrontierWinners } from '@/components/inference/utils/e2eFrontier';
import { resolveXAxisField } from '@/components/inference/utils/resolveXAxisField';
import {
applyQuickFilters,
computeAvailableQuickFilters,
Expand Down Expand Up @@ -86,39 +83,14 @@ function e2eParetoIds(
selectedYAxisMetric: string,
percentile: string,
): Set<number> | null {
const e2eChartDef = (chartDefinitions as ChartDefinition[]).find((c) => c.chartType === 'e2e');
if (!e2eChartDef) return null;
const dir = e2eChartDef[`${selectedYAxisMetric}_roofline` as keyof ChartDefinition] as
| ParetoDirection
| undefined;
if (!dir) return null;
const frontierFn = paretoFrontForDirection(dir);
// Percentile-prefixed e2e-latency field name (e.g. 'p90_e2el').
const e2elField = withPercentile('median_e2el', percentile);
const metricKey = selectedYAxisMetric.replace('y_', '') as YAxisMetricKey;

// Re-frame each candidate point in (e2el, y) space, then compute the
// pareto per (hwKey, precision, date) bucket — frontiers don't span dates
// (a May 17 point can't dominate a May 15 plot).
const byGroup = new Map<string, InferenceData[]>();
for (const p of points) {
const yValue = (p[metricKey] as { y?: number } | undefined)?.y;
const xValue = (p as unknown as Record<string, unknown>)[e2elField];
if (typeof xValue !== 'number' || !Number.isFinite(xValue)) continue;
if (typeof yValue !== 'number' || !Number.isFinite(yValue)) continue;
const key = `${p.hwKey}|${p.precision}|${p.date}`;
let bucket = byGroup.get(key);
if (!bucket) {
bucket = [];
byGroup.set(key, bucket);
}
bucket.push({ ...p, x: xValue, y: yValue });
}
// Shared seed with the overlay path (processOverlayChartData) so both draw
// the SAME e2e-restricted frontier. null = the y-metric has no e2e roofline
// direction → caller skips filtering. Only persisted DB rows carry ids to pin.
const winners = e2eFrontierWinners(points, selectedYAxisMetric, percentile);
if (winners === null) return null;
const ids = new Set<number>();
for (const bucket of byGroup.values()) {
for (const f of frontierFn(bucket)) {
if (isPersistedBenchmarkId(f.id)) ids.add(f.id);
}
for (const winner of winners) {
if (isPersistedBenchmarkId(winner.id)) ids.add(winner.id);
}
return ids;
}
Expand Down Expand Up @@ -399,81 +371,49 @@ export function useChartData(
(chartDefinitions as ChartDefinition[]).map((chartDef) => {
const metricKey = selectedYAxisMetric.replace('y_', '') as YAxisMetricKey;

// Default x-axis = chart's natural latency metric, percentile-adjusted
// for the agentic case (median_e2el → p99_e2el etc.). Percentiles only
// exist for agentic scenarios; fixed-seq benchmarks have no p90_/p99_
// columns, and the percentile selector is hidden for them — but its
// state persists at the 'p90' default across mode/sequence switches.
// Applying that stale percentile to a fixed-seq metric yields a null
// column (e.g. p90_intvty), which renders as x=0/NaN and drops the
// point from the chart. Force median for non-agentic so the natural
// metric (median_intvty / median_e2el) is used.
// Resolve which data field the x-axis plots — shared with the overlay
// path (processOverlayChartData) via resolveXAxisField so the two
// can't drift. Labels/headings stay here (display-only) and follow the
// resolver's branch discriminant.
const isAgentic = selectedSequence === Sequence.AgenticTraces;
const naturalX = withPercentile(
chartDef.x,
isAgentic ? selectedPercentile : 'median',
) as keyof AggDataEntry;
let xAxisField: keyof AggDataEntry = naturalX;
let xAxisLabel = chartDef.x_label;

const metricTitle =
(chartDef[`${selectedYAxisMetric}_title` as keyof ChartDefinition] as string) || '';
const isInputMetric = metricTitle.toLowerCase().includes('input');

// Resolve the effective x-axis override per chart type
const effectiveXMetric =
chartDef.chartType === 'e2e' ? selectedE2eXAxisMetric : selectedXAxisMetric;
// The TTFT override is now any *_ttft metric (not just p90_ttft) — the
// x-axis-mode picker reconciles the percentile prefix based on sequence
// kind (fixed-seq → median, agentic → user-picked percentile).
const isTtftOverride =
typeof effectiveXMetric === 'string' && effectiveXMetric.endsWith('_ttft');
const resolved = resolveXAxisField(chartDef, selectedYAxisMetric, effectiveXMetric, {
isAgentic,
percentile: selectedPercentile,
});
const naturalX = resolved.naturalX as keyof AggDataEntry;
const xAxisField = resolved.xAxisField as keyof AggDataEntry;
const { isTtftOverride } = resolved;

const ttftPctl = isTtftOverride
? (effectiveXMetric as string).replace(/_ttft$/u, '')
: 'p90';
const ttftPctlWord = ttftPctl === 'median' ? 'Median' : ttftPctl.toUpperCase();
const ttftLabel = `${ttftPctlWord} Time To First Token (s)`;

if (
effectiveXMetric &&
chartDef.chartType === 'interactivity' &&
isInputMetric &&
!isAgentic
) {
xAxisField = effectiveXMetric as keyof AggDataEntry;
let xAxisLabel = chartDef.x_label;
if (resolved.branch === 'user-input-override') {
const labelKey = `${selectedYAxisMetric}_x_label` as keyof ChartDefinition;
if (effectiveXMetric === chartDef[`${selectedYAxisMetric}_x` as keyof ChartDefinition]) {
xAxisLabel = (chartDef[labelKey] as string) || chartDef.x_label;
} else {
xAxisLabel = isTtftOverride ? ttftLabel : chartDef.x_label;
}
} else if (chartDef.chartType === 'interactivity' && isInputMetric) {
// Agentic falls through here too — the manual X-axis dropdown is
// hidden in agentic mode (would double up with the percentile
// selector), so the config default + percentile post-processing
// below drives the x axis.
const xOverrideKey = `${selectedYAxisMetric}_x` as keyof ChartDefinition;
} else if (resolved.branch === 'config-input-override') {
const xLabelOverrideKey = `${selectedYAxisMetric}_x_label` as keyof ChartDefinition;
xAxisField = (chartDef[xOverrideKey] as keyof AggDataEntry) || chartDef.x;
xAxisLabel = (chartDef[xLabelOverrideKey] as string) || chartDef.x_label;
} else if (chartDef.chartType === 'e2e' && isTtftOverride) {
xAxisField = effectiveXMetric as keyof AggDataEntry;
} else if (resolved.branch === 'e2e-ttft-override') {
xAxisLabel = ttftLabel;
}

// Agentic: rewrite the resolved x metric to the chosen percentile,
// and relabel accordingly. Both have to be updated unconditionally —
// xAxisField may already be percentile-adjusted (via naturalX) while
// xAxisLabel still carries the raw chartDef.x_label prefix.
// The chart heading ("vs. <latency>") is also rewritten to include
// the percentile so the title above the plot reflects what's drawn.
// Agentic: relabel to the chosen percentile (the resolver already
// rewrote the field) — xAxisLabel still carries the raw chartDef
// prefix. The chart heading ("vs. <latency>") is also rewritten so the
// title above the plot reflects what's drawn.
const headingKey = `${selectedYAxisMetric}_heading` as keyof ChartDefinition;
let chartHeading = (chartDef[headingKey] as string) || chartDef.heading;
if (isAgentic) {
xAxisField = withPercentile(
xAxisField as string,
selectedPercentile,
) as keyof AggDataEntry;
const pctlWord = selectedPercentile.toUpperCase();
xAxisLabel = xAxisLabel.replace(/^(?:Median|Mean|P75|P90|P95|P99(?:\.9)?)\b/iu, pctlWord);
chartHeading = chartHeading.replace(
Expand Down
11 changes: 10 additions & 1 deletion packages/app/src/components/inference/ui/ChartDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -380,12 +380,19 @@ export default function ChartDisplay() {
if (!rawData || rawData.data.length === 0) return null;

const effectiveXMetric = chartType === 'e2e' ? selectedE2eXAxisMetric : selectedXAxisMetric;
const isAgentic = sequenceKind(selectedSequence) === 'agentic';
const processed = processOverlayChartData(
rawData.data,
chartType,
selectedYAxisMetric,
effectiveXMetric,
{ isAgentic: sequenceKind(selectedSequence) === 'agentic' },
{
isAgentic,
selectedPercentile,
// Same gate useChartData applies to the official points — on any
// non-e2e x-mode, agentic rooflines are restricted to e2e winners.
restrictToE2eFrontier: isAgentic && selectedXAxisMode !== 'e2e',
},
);

let overlayPoints = processed;
Expand Down Expand Up @@ -425,6 +432,8 @@ export default function ChartDisplay() {
selectedYAxisMetric,
selectedXAxisMetric,
selectedE2eXAxisMetric,
selectedPercentile,
selectedXAxisMode,
compareGpuPair,
]);

Expand Down
Loading
Loading