From abb357eb62a6981dd61c99c0870d920248c23308 Mon Sep 17 00:00:00 2001 From: Oseltamivir <58582368+Oseltamivir@users.noreply.github.com> Date: Sat, 8 Aug 2026 01:03:42 +0800 Subject: [PATCH 1/3] feat(collectivex): chart kv-transfer scaling and lead kv-only runs with it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kv card rendered below the EP chart, so a kv-only run led with a legitimately empty chart and read as having no data. The kv section now renders above the EP explorer and grows a D3 chart: aggregate pull GB/s or burst latency against batch size (at the largest measured ISL, the concurrency-scaling story) or against ISL (at batch 1, the single-request handoff), with page-size and direction toggles, per-case series colored like the EP explorer, run-index dashes, and a toggleable legend. Paged rows only; the single-descriptor bulk ceiling stays a table column. 中文:此前 kv 卡片位于 EP 图表之下,仅含 kv 的运行首屏是一张必然为空的 图表,看似没有数据。现将 kv 区块移至 EP 浏览器之上,并新增 D3 图表: 聚合 pull 带宽(GB/s)或突发延迟对批大小(取最大实测 ISL,体现并发扩展) 或对 ISL(取批 1,体现单请求交接)作图,附页大小与方向切换、与 EP 一致 的按配置着色和按运行虚线、可切换图例。仅分页行入图;单描述符 bulk 上限 保留为表格列。 --- packages/app/cypress/e2e/collectivex.cy.ts | 32 ++ .../collectivex/CollectiveXDisplay.tsx | 6 +- .../collectivex/CollectiveXKvChart.tsx | 198 +++++++++++ .../collectivex/CollectiveXKvSection.tsx | 332 ++++++++++++++++++ .../collectivex/CollectiveXKvTable.tsx | 153 -------- .../src/components/collectivex/data.test.ts | 99 +++++- .../app/src/components/collectivex/data.ts | 60 ++++ 7 files changed, 724 insertions(+), 156 deletions(-) create mode 100644 packages/app/src/components/collectivex/CollectiveXKvChart.tsx create mode 100644 packages/app/src/components/collectivex/CollectiveXKvSection.tsx delete mode 100644 packages/app/src/components/collectivex/CollectiveXKvTable.tsx diff --git a/packages/app/cypress/e2e/collectivex.cy.ts b/packages/app/cypress/e2e/collectivex.cy.ts index ebdc623f7..1645fb23c 100644 --- a/packages/app/cypress/e2e/collectivex.cy.ts +++ b/packages/app/cypress/e2e/collectivex.cy.ts @@ -525,6 +525,38 @@ describe('CollectiveX kv-transfer card', () => { ); }); + it('plots the kv chart and switches metric, axis, and page size', () => { + installRuns([kvDataset]); + installRun(kvDataset); + openCollectiveX(); + // Default view: aggregate GB/s vs batch at the largest ISL, page 64, pull. + // The measured fixture case carries paged-64 rows at batch 1 and 16. + cy.get('[data-testid="collectivex-kv-chart"]').should('be.visible'); + cy.get('[data-testid="collectivex-kv-chart"] circle').should('have.length', 2); + cy.get('[data-testid="collectivex-kv-chart"]').should( + 'contain.text', + 'Aggregate pull bandwidth at p50 (GB/s)', + ); + // Metric toggle swaps the y axis to burst latency. + cy.get('[data-testid="collectivex-kv-metric-toggle"]').contains('button', 'ms').click(); + cy.get('[data-testid="collectivex-kv-chart"]').should( + 'contain.text', + 'Burst completion latency p50 (ms)', + ); + // ISL on the x axis pins batch 1: one paged-64 row in the fixture. + cy.get('[data-testid="collectivex-kv-xaxis-toggle"]').contains('button', 'ISL').click(); + cy.get('[data-testid="collectivex-kv-chart"] circle').should('have.length', 1); + // Page 16 keeps a single batch-1 row. + cy.get('[data-testid="collectivex-kv-page-toggle"]').contains('button', '16').click(); + cy.get('[data-testid="collectivex-kv-chart"] circle').should('have.length', 1); + // The kv section renders above the EP explorer chart. + cy.get('[data-testid="collectivex-kv-table"]').then(($kv) => { + cy.get('[data-testid="collectivex-main-chart"]').then(($chart) => { + expect($kv[0].compareDocumentPosition($chart[0]) & 4).to.equal(4); + }); + }); + }); + it('renders no kv card for an EP-only run', () => { installRuns(); installRun(); diff --git a/packages/app/src/components/collectivex/CollectiveXDisplay.tsx b/packages/app/src/components/collectivex/CollectiveXDisplay.tsx index 6c3c1c519..55406f6aa 100644 --- a/packages/app/src/components/collectivex/CollectiveXDisplay.tsx +++ b/packages/app/src/components/collectivex/CollectiveXDisplay.tsx @@ -26,7 +26,7 @@ import { useLocale } from '@/lib/use-locale'; import { CollectiveXChart } from './CollectiveXChart'; import { CollectiveXInventory } from './CollectiveXInventory'; -import { CollectiveXKvTable } from './CollectiveXKvTable'; +import { CollectiveXKvSection } from './CollectiveXKvSection'; import { CollectiveXRunsTable } from './CollectiveXRunsTable'; import { collectiveXColorKey, @@ -862,6 +862,9 @@ export default function CollectiveXDisplay() {
{t.noSeries}
)} + {/* KV-transfer cases lead for kv-only runs: the EP chart below is + legitimately empty for them and must not bury the selected data. */} ++ No measured kv rows match the selected page size and direction. +
+{row.detail ?? row.reason}
+ )} ++ {rows.length} cases · {measured} measured · {strings.description} +
+ {measuredCases.length > 0 && ( + <> +{row.detail ?? row.reason}
- )} -- {rows.length} cases · {measured} measured · {strings.description} -
-| {t.shown} | {t.run} | {t.result} | +{t.suites} | {t.cases} | {t.points} | {t.skus} | @@ -112,6 +120,11 @@ export function CollectiveXRunsTable({ const deleting = deletingRunIds.has(run.run_id); const conclusion = run.conclusion ?? t.pending; const selectedRunIndex = selectedRunIndexById.get(run.run_id); + // Summaries stored before the kv suite carry no kv_cases: EP-only. + const kvRequested = run.kv_cases?.requested ?? 0; + const kvMeasured = run.kv_cases?.measured ?? 0; + const epRequested = run.requested_cases - kvRequested; + const epMeasured = run.measured_cases - kvMeasured; const lineDasharray = selectedRunIndex === undefined ? null : collectiveXRunDasharray(selectedRunIndex); return ( @@ -191,6 +204,34 @@ export function CollectiveXRunsTable({ {conclusion} +
+
+ {epRequested > 0 && (
+
+ EP
+
+ )}
+ {kvRequested > 0 && (
+
+ KV
+
+ )}
+
+ |
{run.measured_cases}/{run.requested_cases} |
|---|