GitHub Actions commited on
Commit
1683f65
·
1 Parent(s): 92ad589

sync from abhijitramesh/webgpu-bench@f0e4a60c2d

Browse files
Files changed (3) hide show
  1. js/app.js +8 -11
  2. js/data.js +34 -0
  3. js/tables.js +1 -10
js/app.js CHANGED
@@ -1,4 +1,4 @@
1
- import { loadData, filterResults, selectBestResults, expandCpuRows, withSyntheticCpuRows } from './data.js';
2
  import { initFilters, populateQuantOptions, getFilters, resetFilters } from './filters.js';
3
  import { renderDecodeChart, renderPrefillChart, renderSizeChart, renderMachineChart, renderCpuGpuChart, renderSpeedupChart } from './charts.js';
4
  import { renderResultsTable, renderErrorTable, renderMachineInfo, renderCpuGpuTable } from './tables.js';
@@ -76,17 +76,14 @@ function render() {
76
  Chart.defaults.plugins.tooltip.bodyColor = isDark ? '#a1a1aa' : '#71717a';
77
 
78
  const filters = getFilters();
79
- // Filter, then collapse to one canonical row per
80
- // (machine, browser, model, variant, backend). Multiple users may submit
81
- // results for the same hardware bucket; this keeps the row with the
82
- // highest iteration count (tiebreak: most recent) so the leaderboard
83
- // shows the most reliable number per cell rather than averaging noisy
84
- // duplicates. withSyntheticCpuRows expands each browser-flow record's
85
- // cpu_baseline_* into a sibling CPU row so CPU runs (CLI or browser)
86
- // appear as their own row in the main table.
87
  const filtered = selectBestResults(
88
- withSyntheticCpuRows(filterResults(appData.results, filters)),
89
- );
90
 
91
  // Summary cards — counts tween from previous value to new on filter changes
92
  // and from 0 on first paint (since `data-value` defaults to "0").
 
1
+ import { loadData, filterResults, selectBestResults, expandCpuRows, attachCpuBaselineFromCpuRecords } from './data.js';
2
  import { initFilters, populateQuantOptions, getFilters, resetFilters } from './filters.js';
3
  import { renderDecodeChart, renderPrefillChart, renderSizeChart, renderMachineChart, renderCpuGpuChart, renderSpeedupChart } from './charts.js';
4
  import { renderResultsTable, renderErrorTable, renderMachineInfo, renderCpuGpuTable } from './tables.js';
 
76
  Chart.defaults.plugins.tooltip.bodyColor = isDark ? '#a1a1aa' : '#71717a';
77
 
78
  const filters = getFilters();
79
+ // Filter, attach CPU baseline values (folds CLI-flow CPU records onto
80
+ // their GPU sibling so both submission paths produce one row per cell),
81
+ // collapse to one canonical row per (machine, browser, model, variant,
82
+ // backend), then drop the now-redundant CPU rows. The CPU numbers stay
83
+ // visible via the cpu_baseline_* columns on each GPU row.
 
 
 
84
  const filtered = selectBestResults(
85
+ attachCpuBaselineFromCpuRecords(filterResults(appData.results, filters)),
86
+ ).filter(r => r.nGpuLayers !== 0);
87
 
88
  // Summary cards — counts tween from previous value to new on filter changes
89
  // and from 0 on first paint (since `data-value` defaults to "0").
js/data.js CHANGED
@@ -160,6 +160,40 @@ export function selectBestResults(records) {
160
  return [...bestByCell.values()];
161
  }
162
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
  /* Synthesize a CPU row for every browser-flow GPU record (the in-page
164
  bench measures one CPU pass per variant alongside the GPU iterations
165
  and stamps the result on the same record via cpu_baseline_*). Returns
 
160
  return [...bestByCell.values()];
161
  }
162
 
163
+ /* For CLI-flow records that ship CPU and GPU as separate dataset entries,
164
+ look up each GPU record's matching CPU companion (same machine, browser,
165
+ model, variant) and copy its perf into cpu_baseline_*. After this pass,
166
+ GPU records from both submission paths (browser, CLI) carry their CPU
167
+ baseline inline, so the main table can render a single row per cell with
168
+ both numbers side-by-side. No-op on records that already have
169
+ cpu_baseline_* (e.g. browser-flow records, where controller.makeRecord
170
+ embeds it at write time). */
171
+ export function attachCpuBaselineFromCpuRecords(results) {
172
+ const cpuByCell = new Map();
173
+ for (const r of results) {
174
+ if (r.nGpuLayers === 0 && r.status === 'done' && (r.decode_tok_s != null || r.prefill_tok_s != null)) {
175
+ const key = `${r.machineSlug}|${r.browser}|${r.model}|${r.variant}`;
176
+ const cur = cpuByCell.get(key);
177
+ // Most-recent wins on tiebreak — matches selectBestResults() semantics.
178
+ if (!cur || (r.timestamp || '') > (cur.timestamp || '')) {
179
+ cpuByCell.set(key, r);
180
+ }
181
+ }
182
+ }
183
+ return results.map(r => {
184
+ if (r.nGpuLayers === 0) return r;
185
+ if (r.cpu_baseline_decode_tok_s != null || r.cpu_baseline_prefill_tok_s != null) return r;
186
+ const key = `${r.machineSlug}|${r.browser}|${r.model}|${r.variant}`;
187
+ const cpu = cpuByCell.get(key);
188
+ if (!cpu) return r;
189
+ return {
190
+ ...r,
191
+ cpu_baseline_decode_tok_s: cpu.decode_tok_s ?? null,
192
+ cpu_baseline_prefill_tok_s: cpu.prefill_tok_s ?? null,
193
+ };
194
+ });
195
+ }
196
+
197
  /* Synthesize a CPU row for every browser-flow GPU record (the in-page
198
  bench measures one CPU pass per variant alongside the GPU iterations
199
  and stamps the result on the same record via cpu_baseline_*). Returns
js/tables.js CHANGED
@@ -8,7 +8,7 @@ const NUM_KEYS = new Set([
8
  'sizeMB', 'decode_tok_s', 'prefill_tok_s',
9
  'cpu_baseline_decode_tok_s', 'cpu_baseline_prefill_tok_s',
10
  'n_eval', 't_eval_ms',
11
- 'n_p_eval', 't_p_eval_ms', 'wallTimeMs', 'consistency_rate', 'nGpuLayers',
12
  ]);
13
 
14
  function sortResults(results, key, dir) {
@@ -72,7 +72,6 @@ export function renderResultsTable(results) {
72
  { key: 'sizeMB', label: 'Size (MB)', priority: 3 },
73
  { key: 'browser', label: 'Browser', priority: 2 },
74
  { key: 'submittedBy', label: 'Submitter', priority: 2 },
75
- { key: 'nGpuLayers', label: 'Backend', priority: 2 },
76
  { key: 'status', label: 'Status', priority: 1 },
77
  { key: 'buildType', label: 'Build', priority: 3 },
78
  { key: 'webgpuAvailable', label: 'WebGPU', priority: 3 },
@@ -117,14 +116,6 @@ export function renderResultsTable(results) {
117
  ? '<span class="badge badge--pass">PASS</span>'
118
  : '<span class="badge badge--fail">FAIL</span>';
119
  break;
120
- case 'nGpuLayers':
121
- if (r.nGpuLayers != null) {
122
- const isCpu = r.nGpuLayers === 0;
123
- html += `<span class="badge ${isCpu ? 'badge--cpu' : 'badge--webgpu'}">${isCpu ? 'CPU' : 'WebGPU'}</span>`;
124
- } else {
125
- html += '<span class="text-muted">\u2014</span>';
126
- }
127
- break;
128
  case 'webgpuAvailable':
129
  html += r.webgpuAvailable
130
  ? '<span class="badge badge--yes">Yes</span>'
 
8
  'sizeMB', 'decode_tok_s', 'prefill_tok_s',
9
  'cpu_baseline_decode_tok_s', 'cpu_baseline_prefill_tok_s',
10
  'n_eval', 't_eval_ms',
11
+ 'n_p_eval', 't_p_eval_ms', 'wallTimeMs', 'consistency_rate',
12
  ]);
13
 
14
  function sortResults(results, key, dir) {
 
72
  { key: 'sizeMB', label: 'Size (MB)', priority: 3 },
73
  { key: 'browser', label: 'Browser', priority: 2 },
74
  { key: 'submittedBy', label: 'Submitter', priority: 2 },
 
75
  { key: 'status', label: 'Status', priority: 1 },
76
  { key: 'buildType', label: 'Build', priority: 3 },
77
  { key: 'webgpuAvailable', label: 'WebGPU', priority: 3 },
 
116
  ? '<span class="badge badge--pass">PASS</span>'
117
  : '<span class="badge badge--fail">FAIL</span>';
118
  break;
 
 
 
 
 
 
 
 
119
  case 'webgpuAvailable':
120
  html += r.webgpuAvailable
121
  ? '<span class="badge badge--yes">Yes</span>'