GitHub Actions commited on
Commit
ed5d4b6
·
1 Parent(s): 86d8a2e

sync from abhijitramesh/webgpu-bench@ef7e64472d

Browse files
build/asyncify/build-info.json CHANGED
@@ -2,5 +2,5 @@
2
  "llamaCppCommit": "f22c8021d213567942a3d0134692e70f02f28f3a",
3
  "llamaCppDescribe": "b8981-3-gf22c8021d",
4
  "dawnTag": "v20260317.182325",
5
- "builtAt": "2026-05-11T23:04:49Z"
6
  }
 
2
  "llamaCppCommit": "f22c8021d213567942a3d0134692e70f02f28f3a",
3
  "llamaCppDescribe": "b8981-3-gf22c8021d",
4
  "dawnTag": "v20260317.182325",
5
+ "builtAt": "2026-05-11T23:13:42Z"
6
  }
build/jspi/build-info.json CHANGED
@@ -2,5 +2,5 @@
2
  "llamaCppCommit": "f22c8021d213567942a3d0134692e70f02f28f3a",
3
  "llamaCppDescribe": "b8981-3-gf22c8021d",
4
  "dawnTag": "v20260317.182325",
5
- "builtAt": "2026-05-11T23:00:38Z"
6
  }
 
2
  "llamaCppCommit": "f22c8021d213567942a3d0134692e70f02f28f3a",
3
  "llamaCppDescribe": "b8981-3-gf22c8021d",
4
  "dawnTag": "v20260317.182325",
5
+ "builtAt": "2026-05-11T23:10:21Z"
6
  }
js/app.js CHANGED
@@ -224,7 +224,7 @@ function renderHeroMeta(data) {
224
  /* Tween numeric content from 0 to a target. CSS-only via @property would
225
  need server-side @property registration to work in older Safari; keep
226
  this 12-line JS tween for predictability. */
227
- export function animateCount(el, target, { decimals = 0, duration = 600 } = {}) {
228
  if (!el) return;
229
  const start = parseFloat(el.dataset.value || '0') || 0;
230
  const end = Number(target) || 0;
 
224
  /* Tween numeric content from 0 to a target. CSS-only via @property would
225
  need server-side @property registration to work in older Safari; keep
226
  this 12-line JS tween for predictability. */
227
+ function animateCount(el, target, { decimals = 0, duration = 600 } = {}) {
228
  if (!el) return;
229
  const start = parseFloat(el.dataset.value || '0') || 0;
230
  const end = Number(target) || 0;
js/charts.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BROWSER_COLORS, quantSortKey, groupBy, formatTokS } from './utils.js';
2
  import { expandCpuRows } from './data.js';
3
 
4
  // Global Chart.js theme — uses the site's font tokens and a calm tooltip
@@ -78,14 +78,10 @@ export function renderDecodeChart(results) {
78
 
79
  const passed = results.filter(r => r.status === 'done' && r.decode_tok_s != null);
80
  if (passed.length === 0) {
81
- canvas.parentElement.querySelector('.chart-empty')?.remove();
82
- const msg = document.createElement('div');
83
- msg.className = 'chart-empty';
84
- msg.textContent = 'No data';
85
- canvas.parentElement.appendChild(msg);
86
  return;
87
  }
88
- canvas.parentElement.querySelector('.chart-empty')?.remove();
89
 
90
  const byBrowser = groupBy(passed, 'browser');
91
  const allQuants = [...new Set(passed.map(r => r.variant))].sort((a, b) => quantSortKey(a) - quantSortKey(b));
@@ -95,12 +91,7 @@ export function renderDecodeChart(results) {
95
  return {
96
  label: browser,
97
  backgroundColor: BROWSER_COLORS[browser] || '#888',
98
- data: allQuants.map(q => {
99
- const group = byQuant[q];
100
- if (!group) return null;
101
- const vals = group.map(r => r.decode_tok_s).filter(v => v != null);
102
- return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
103
- }),
104
  };
105
  });
106
 
@@ -130,14 +121,10 @@ export function renderPrefillChart(results) {
130
 
131
  const passed = results.filter(r => r.status === 'done' && r.prefill_tok_s != null);
132
  if (passed.length === 0) {
133
- canvas.parentElement.querySelector('.chart-empty')?.remove();
134
- const msg = document.createElement('div');
135
- msg.className = 'chart-empty';
136
- msg.textContent = 'No data';
137
- canvas.parentElement.appendChild(msg);
138
  return;
139
  }
140
- canvas.parentElement.querySelector('.chart-empty')?.remove();
141
 
142
  const byBrowser = groupBy(passed, 'browser');
143
  const allQuants = [...new Set(passed.map(r => r.variant))].sort((a, b) => quantSortKey(a) - quantSortKey(b));
@@ -147,12 +134,7 @@ export function renderPrefillChart(results) {
147
  return {
148
  label: browser,
149
  backgroundColor: BROWSER_COLORS[browser] || '#888',
150
- data: allQuants.map(q => {
151
- const group = byQuant[q];
152
- if (!group) return null;
153
- const vals = group.map(r => r.prefill_tok_s).filter(v => v != null);
154
- return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
155
- }),
156
  };
157
  });
158
 
@@ -182,14 +164,10 @@ export function renderSizeChart(results) {
182
 
183
  const passed = results.filter(r => r.status === 'done' && r.decode_tok_s != null && r.sizeMB);
184
  if (passed.length === 0) {
185
- canvas.parentElement.querySelector('.chart-empty')?.remove();
186
- const msg = document.createElement('div');
187
- msg.className = 'chart-empty';
188
- msg.textContent = 'No data';
189
- canvas.parentElement.appendChild(msg);
190
  return;
191
  }
192
- canvas.parentElement.querySelector('.chart-empty')?.remove();
193
 
194
  const byBrowser = groupBy(passed, 'browser');
195
 
@@ -245,11 +223,6 @@ const METRIC_LABELS = {
245
  prefill_tok_s: 'Prefill tok/s',
246
  };
247
 
248
- function avgBy(items, field) {
249
- const vals = items.map(r => r[field]).filter(v => v != null);
250
- return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
251
- }
252
-
253
  // CPU is pinned to d=0 by the runner, so apples-to-apples means reading
254
  // GPU's d=0 number. The CPU side keeps its bare metric (CPU records are
255
  // depth-pinned to 0 either way); GPU reads `<metric>_d0`. Plain-Run
 
1
+ import { BROWSER_COLORS, quantSortKey, groupBy, formatTokS, avgBy } from './utils.js';
2
  import { expandCpuRows } from './data.js';
3
 
4
  // Global Chart.js theme — uses the site's font tokens and a calm tooltip
 
78
 
79
  const passed = results.filter(r => r.status === 'done' && r.decode_tok_s != null);
80
  if (passed.length === 0) {
81
+ showEmptyState(canvas);
 
 
 
 
82
  return;
83
  }
84
+ clearEmptyState(canvas);
85
 
86
  const byBrowser = groupBy(passed, 'browser');
87
  const allQuants = [...new Set(passed.map(r => r.variant))].sort((a, b) => quantSortKey(a) - quantSortKey(b));
 
91
  return {
92
  label: browser,
93
  backgroundColor: BROWSER_COLORS[browser] || '#888',
94
+ data: allQuants.map(q => avgBy(byQuant[q] || [], 'decode_tok_s')),
 
 
 
 
 
95
  };
96
  });
97
 
 
121
 
122
  const passed = results.filter(r => r.status === 'done' && r.prefill_tok_s != null);
123
  if (passed.length === 0) {
124
+ showEmptyState(canvas);
 
 
 
 
125
  return;
126
  }
127
+ clearEmptyState(canvas);
128
 
129
  const byBrowser = groupBy(passed, 'browser');
130
  const allQuants = [...new Set(passed.map(r => r.variant))].sort((a, b) => quantSortKey(a) - quantSortKey(b));
 
134
  return {
135
  label: browser,
136
  backgroundColor: BROWSER_COLORS[browser] || '#888',
137
+ data: allQuants.map(q => avgBy(byQuant[q] || [], 'prefill_tok_s')),
 
 
 
 
 
138
  };
139
  });
140
 
 
164
 
165
  const passed = results.filter(r => r.status === 'done' && r.decode_tok_s != null && r.sizeMB);
166
  if (passed.length === 0) {
167
+ showEmptyState(canvas);
 
 
 
 
168
  return;
169
  }
170
+ clearEmptyState(canvas);
171
 
172
  const byBrowser = groupBy(passed, 'browser');
173
 
 
223
  prefill_tok_s: 'Prefill tok/s',
224
  };
225
 
 
 
 
 
 
226
  // CPU is pinned to d=0 by the runner, so apples-to-apples means reading
227
  // GPU's d=0 number. The CPU side keeps its bare metric (CPU records are
228
  // depth-pinned to 0 either way); GPU reads `<metric>_d0`. Plain-Run
js/dataset.js CHANGED
@@ -31,7 +31,7 @@ const MAX_FETCH = 1000;
31
  look newer than `sinceISO` (with a clock-skew buffer applied). On any
32
  network/CORS/parse failure, returns an empty array — the dashboard then
33
  silently falls back to the static combined.json baseline. */
34
- export async function listRecentRunFiles(datasetRepo, sinceISO) {
35
  if (!datasetRepo) return [];
36
  // Cache-bust the listing — HF's CDN can serve a stale tree response, and
37
  // we specifically care about reading-our-own-write after a submit.
@@ -64,19 +64,12 @@ async function fetchRunFile(datasetRepo, filePath) {
64
  return resp.json();
65
  }
66
 
67
- /* List the dataset tree and download every file in `runs/`. Pure-live
68
- variant of fetchRecentRuns — no cutoff, returns the entire dataset.
69
- Caller is responsible for rate-limiting/caching. */
70
  export async function fetchAllRuns(datasetRepo) {
71
  return fetchRunsBatch(datasetRepo, await listRecentRunFiles(datasetRepo, null));
72
  }
73
 
74
- /* List the dataset tree and download every file that's newer than the
75
- baseline's generatedAt. Kept for callers that still want a delta view. */
76
- export async function fetchRecentRuns(datasetRepo, sinceISO) {
77
- return fetchRunsBatch(datasetRepo, await listRecentRunFiles(datasetRepo, sinceISO));
78
- }
79
-
80
  async function fetchRunsBatch(datasetRepo, files) {
81
  if (files.length === 0) return { records: [], machines: [], fileCount: 0 };
82
 
 
31
  look newer than `sinceISO` (with a clock-skew buffer applied). On any
32
  network/CORS/parse failure, returns an empty array — the dashboard then
33
  silently falls back to the static combined.json baseline. */
34
+ async function listRecentRunFiles(datasetRepo, sinceISO) {
35
  if (!datasetRepo) return [];
36
  // Cache-bust the listing — HF's CDN can serve a stale tree response, and
37
  // we specifically care about reading-our-own-write after a submit.
 
64
  return resp.json();
65
  }
66
 
67
+ /* List the dataset tree and download every file in `runs/`. Caller is
68
+ responsible for rate-limiting/caching. */
 
69
  export async function fetchAllRuns(datasetRepo) {
70
  return fetchRunsBatch(datasetRepo, await listRecentRunFiles(datasetRepo, null));
71
  }
72
 
 
 
 
 
 
 
73
  async function fetchRunsBatch(datasetRepo, files) {
74
  if (files.length === 0) return { records: [], machines: [], fileCount: 0 };
75
 
js/tables.js CHANGED
@@ -1,4 +1,4 @@
1
- import { formatTokS, formatMs, categorizeError, groupBy, quantSortKey } from './utils.js';
2
  import { expandCpuRows } from './data.js';
3
 
4
  let lastResults = [];
@@ -373,11 +373,6 @@ export function renderCpuGpuTable(results) {
373
  return;
374
  }
375
 
376
- function avg(items, field) {
377
- const vals = items.map(r => r[field]).filter(v => v != null);
378
- return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
379
- }
380
-
381
  const gpuBrowsers = [...new Set(gpuResults.map(r => r.browser))].sort();
382
 
383
  const cpuByModelVariant = groupBy(cpuResults, r => `${r.model}::${r.variant}`);
@@ -437,7 +432,7 @@ export function renderCpuGpuTable(results) {
437
 
438
  // CPU columns
439
  for (const m of METRICS) {
440
- const val = avg(cpuItems, m.cpuField);
441
  html += `<td><span class="mono">${formatTokS(val)}</span></td>`;
442
  }
443
 
@@ -445,8 +440,8 @@ export function renderCpuGpuTable(results) {
445
  for (const b of gpuBrowsers) {
446
  const gpuItems = gpuByBrowser[b] || [];
447
  for (const m of METRICS) {
448
- const cpuVal = avg(cpuItems, m.cpuField);
449
- const gpuVal = avg(gpuItems, m.gpuField);
450
  const speedup = cpuVal && gpuVal ? gpuVal / cpuVal : null;
451
  const cls = speedup == null ? '' : speedup >= 3 ? 'text-success' : speedup >= 1.5 ? '' : speedup >= 1 ? 'text-muted' : 'text-error';
452
  html += `<td><span class="mono">${formatTokS(gpuVal)}</span></td>`;
 
1
+ import { formatTokS, formatMs, categorizeError, groupBy, quantSortKey, avgBy } from './utils.js';
2
  import { expandCpuRows } from './data.js';
3
 
4
  let lastResults = [];
 
373
  return;
374
  }
375
 
 
 
 
 
 
376
  const gpuBrowsers = [...new Set(gpuResults.map(r => r.browser))].sort();
377
 
378
  const cpuByModelVariant = groupBy(cpuResults, r => `${r.model}::${r.variant}`);
 
432
 
433
  // CPU columns
434
  for (const m of METRICS) {
435
+ const val = avgBy(cpuItems, m.cpuField);
436
  html += `<td><span class="mono">${formatTokS(val)}</span></td>`;
437
  }
438
 
 
440
  for (const b of gpuBrowsers) {
441
  const gpuItems = gpuByBrowser[b] || [];
442
  for (const m of METRICS) {
443
+ const cpuVal = avgBy(cpuItems, m.cpuField);
444
+ const gpuVal = avgBy(gpuItems, m.gpuField);
445
  const speedup = cpuVal && gpuVal ? gpuVal / cpuVal : null;
446
  const cls = speedup == null ? '' : speedup >= 3 ? 'text-success' : speedup >= 1.5 ? '' : speedup >= 1 ? 'text-muted' : 'text-error';
447
  html += `<td><span class="mono">${formatTokS(gpuVal)}</span></td>`;
js/utils.js CHANGED
@@ -52,3 +52,8 @@ export function groupBy(arr, keyFn) {
52
  }
53
  return map;
54
  }
 
 
 
 
 
 
52
  }
53
  return map;
54
  }
55
+
56
+ export function avgBy(items, field) {
57
+ const vals = items.map(r => r[field]).filter(v => v != null);
58
+ return vals.length ? vals.reduce((a, b) => a + b, 0) / vals.length : null;
59
+ }