GitHub Actions commited on
Commit
aa61dca
·
1 Parent(s): 060e926

sync from abhijitramesh/webgpu-bench@def1735599

Browse files
Files changed (3) hide show
  1. data/combined.json +0 -366
  2. js/data.js +70 -45
  3. js/dataset.js +18 -7
data/combined.json DELETED
@@ -1,366 +0,0 @@
1
- {
2
- "meta": {
3
- "machines": [
4
- {
5
- "slug": "apple-metal-3-4gb-darwin",
6
- "cpus": "apple metal-3",
7
- "platform": "darwin",
8
- "arch": "arm",
9
- "totalMemoryGB": 4,
10
- "submittedAt": "2026-04-25T21:31:12.111Z",
11
- "resultCount": 7,
12
- "passCount": 7,
13
- "llamaCppCommit": null,
14
- "llamaCppDescribe": null,
15
- "submitters": [
16
- {
17
- "name": "abhijitramesh",
18
- "hubId": "5fe0b7319126717e4c356efb",
19
- "avatarUrl": "https://cdn-avatars.huggingface.co/v1/production/uploads/5fe0b7319126717e4c356efb/iAaiUJpDmv1nBN3_ZNGVU.jpeg",
20
- "count": 3,
21
- "latestAt": "2026-04-25T21:15:00.076Z"
22
- },
23
- {
24
- "name": "abhijitramesh",
25
- "hubId": null,
26
- "avatarUrl": null,
27
- "count": 1,
28
- "latestAt": "2026-04-25T04:50:36.488Z"
29
- }
30
- ]
31
- },
32
- {
33
- "slug": "apple-metal-3-8gb-darwin",
34
- "cpus": "apple metal-3",
35
- "platform": "darwin",
36
- "arch": "arm",
37
- "totalMemoryGB": 8,
38
- "submittedAt": "2026-04-25T21:31:12.111Z",
39
- "resultCount": 2,
40
- "passCount": 2,
41
- "llamaCppCommit": null,
42
- "llamaCppDescribe": null,
43
- "submitters": [
44
- {
45
- "name": "abhijitramesh",
46
- "hubId": "5fe0b7319126717e4c356efb",
47
- "avatarUrl": "https://cdn-avatars.huggingface.co/v1/production/uploads/5fe0b7319126717e4c356efb/iAaiUJpDmv1nBN3_ZNGVU.jpeg",
48
- "count": 1,
49
- "latestAt": "2026-04-25T18:38:18.454Z"
50
- }
51
- ]
52
- }
53
- ],
54
- "models": [
55
- "Llama-3.2-1B-Instruct",
56
- "Qwen3-0.6B",
57
- "Qwen3.5-2B",
58
- "gemma-3-270m-it"
59
- ],
60
- "browsers": [
61
- "chromium-147"
62
- ],
63
- "generatedAt": "2026-04-25T21:31:12.161Z"
64
- },
65
- "results": [
66
- {
67
- "machineSlug": "apple-metal-3-4gb-darwin",
68
- "timestamp": "2026-04-25T03:44:12.854Z",
69
- "browser": "chromium-147",
70
- "model": "Llama-3.2-1B-Instruct",
71
- "repo": "unsloth/Llama-3.2-1B-Instruct-GGUF",
72
- "variant": "Q2_K",
73
- "filename": "Llama-3.2-1B-Instruct-Q2_K.gguf",
74
- "sizeMB": 553.96,
75
- "status": "done",
76
- "error": null,
77
- "buildType": "jspi",
78
- "webgpuAvailable": true,
79
- "nGpuLayers": 999,
80
- "wallTimeMs": 108503.70000004768,
81
- "prefill_tok_s": 59.07,
82
- "decode_tok_s": 40.57,
83
- "n_p_eval": 31,
84
- "t_p_eval_ms": 526,
85
- "n_eval": 127,
86
- "t_eval_ms": 3125.7,
87
- "consistency_rate": 0.9688,
88
- "consistency_first_disagree": 43,
89
- "cpu_baseline_prefill_tok_s": 3.93,
90
- "cpu_baseline_decode_tok_s": 3.55,
91
- "llamaCppCommit": null,
92
- "llamaCppDescribe": null,
93
- "dawnTag": null,
94
- "submittedBy": null,
95
- "iterations": 5
96
- },
97
- {
98
- "machineSlug": "apple-metal-3-4gb-darwin",
99
- "timestamp": "2026-04-25T03:47:08.023Z",
100
- "browser": "chromium-147",
101
- "model": "Llama-3.2-1B-Instruct",
102
- "repo": "unsloth/Llama-3.2-1B-Instruct-GGUF",
103
- "variant": "Q4_K_M",
104
- "filename": "Llama-3.2-1B-Instruct-Q4_K_M.gguf",
105
- "sizeMB": 770.28,
106
- "status": "done",
107
- "error": null,
108
- "buildType": "jspi",
109
- "webgpuAvailable": true,
110
- "nGpuLayers": 999,
111
- "wallTimeMs": 174666.89999997616,
112
- "prefill_tok_s": 83.51,
113
- "decode_tok_s": 46.15,
114
- "n_p_eval": 31,
115
- "t_p_eval_ms": 350.5,
116
- "n_eval": 127,
117
- "t_eval_ms": 2820.9,
118
- "consistency_rate": 1,
119
- "consistency_first_disagree": -1,
120
- "cpu_baseline_prefill_tok_s": 9.84,
121
- "cpu_baseline_decode_tok_s": 6.95,
122
- "llamaCppCommit": null,
123
- "llamaCppDescribe": null,
124
- "dawnTag": null,
125
- "submittedBy": null,
126
- "iterations": 5
127
- },
128
- {
129
- "machineSlug": "apple-metal-3-4gb-darwin",
130
- "timestamp": "2026-04-25T03:51:41.928Z",
131
- "browser": "chromium-147",
132
- "model": "Llama-3.2-1B-Instruct",
133
- "repo": "unsloth/Llama-3.2-1B-Instruct-GGUF",
134
- "variant": "Q8_0",
135
- "filename": "Llama-3.2-1B-Instruct-Q8_0.gguf",
136
- "sizeMB": 1259.88,
137
- "status": "done",
138
- "error": null,
139
- "buildType": "jspi",
140
- "webgpuAvailable": true,
141
- "nGpuLayers": 999,
142
- "wallTimeMs": 273256.60000002384,
143
- "prefill_tok_s": 110.2,
144
- "decode_tok_s": 41.82,
145
- "n_p_eval": 31,
146
- "t_p_eval_ms": 267.1,
147
- "n_eval": 127,
148
- "t_eval_ms": 3016.4,
149
- "consistency_rate": 0.9922,
150
- "consistency_first_disagree": 109,
151
- "cpu_baseline_prefill_tok_s": 8.98,
152
- "cpu_baseline_decode_tok_s": 6.61,
153
- "llamaCppCommit": null,
154
- "llamaCppDescribe": null,
155
- "dawnTag": null,
156
- "submittedBy": null,
157
- "iterations": 5
158
- },
159
- {
160
- "machineSlug": "apple-metal-3-4gb-darwin",
161
- "timestamp": "2026-04-25T04:50:36.488Z",
162
- "browser": "chromium-147",
163
- "model": "Qwen3.5-2B",
164
- "repo": "unsloth/Qwen3.5-2B-GGUF",
165
- "variant": "IQ4_XS",
166
- "filename": "Qwen3.5-2B-IQ4_XS.gguf",
167
- "sizeMB": 1118.66,
168
- "status": "done",
169
- "error": null,
170
- "buildType": "jspi",
171
- "webgpuAvailable": true,
172
- "nGpuLayers": 999,
173
- "wallTimeMs": 137132.30000001192,
174
- "prefill_tok_s": 61.42,
175
- "decode_tok_s": 28.23,
176
- "n_p_eval": 30,
177
- "t_p_eval_ms": 1043.3,
178
- "n_eval": 127,
179
- "t_eval_ms": 4552.3,
180
- "consistency_rate": 0.9922,
181
- "consistency_first_disagree": 33,
182
- "cpu_baseline_prefill_tok_s": 2.6,
183
- "cpu_baseline_decode_tok_s": 2.21,
184
- "llamaCppCommit": null,
185
- "llamaCppDescribe": null,
186
- "dawnTag": null,
187
- "submittedBy": {
188
- "name": "abhijitramesh",
189
- "hubId": null,
190
- "avatarUrl": null
191
- },
192
- "iterations": 5
193
- },
194
- {
195
- "machineSlug": "apple-metal-3-4gb-darwin",
196
- "timestamp": "2026-04-25T19:43:30.850Z",
197
- "browser": "chromium-147",
198
- "model": "gemma-3-270m-it",
199
- "repo": "unsloth/gemma-3-270m-it-GGUF",
200
- "variant": "UD-IQ2_XXS",
201
- "filename": "gemma-3-270m-it-UD-IQ2_XXS.gguf",
202
- "sizeMB": 171.76,
203
- "status": "done",
204
- "error": null,
205
- "buildType": "jspi",
206
- "webgpuAvailable": true,
207
- "nGpuLayers": 999,
208
- "wallTimeMs": 44796.59999996424,
209
- "prefill_tok_s": 169.85,
210
- "decode_tok_s": 106.01,
211
- "n_p_eval": 27,
212
- "t_p_eval_ms": 470.3,
213
- "n_eval": 127,
214
- "t_eval_ms": 1194.8,
215
- "consistency_rate": 0.9688,
216
- "consistency_first_disagree": 23,
217
- "cpu_baseline_prefill_tok_s": 23.36,
218
- "cpu_baseline_decode_tok_s": 11.69,
219
- "llamaCppCommit": null,
220
- "llamaCppDescribe": null,
221
- "dawnTag": null,
222
- "submittedBy": {
223
- "name": "abhijitramesh",
224
- "hubId": "5fe0b7319126717e4c356efb",
225
- "avatarUrl": "https://cdn-avatars.huggingface.co/v1/production/uploads/5fe0b7319126717e4c356efb/iAaiUJpDmv1nBN3_ZNGVU.jpeg"
226
- },
227
- "iterations": 5
228
- },
229
- {
230
- "machineSlug": "apple-metal-3-4gb-darwin",
231
- "timestamp": "2026-04-25T19:43:30.850Z",
232
- "browser": "chromium-147",
233
- "model": "gemma-3-270m-it",
234
- "repo": "unsloth/gemma-3-270m-it-GGUF",
235
- "variant": "UD-IQ2_XXS",
236
- "filename": "gemma-3-270m-it-UD-IQ2_XXS.gguf",
237
- "sizeMB": 171.76,
238
- "status": "done",
239
- "error": null,
240
- "buildType": "jspi",
241
- "webgpuAvailable": true,
242
- "nGpuLayers": 999,
243
- "wallTimeMs": 44796.59999996424,
244
- "prefill_tok_s": 169.85,
245
- "decode_tok_s": 106.01,
246
- "n_p_eval": 27,
247
- "t_p_eval_ms": 470.3,
248
- "n_eval": 127,
249
- "t_eval_ms": 1194.8,
250
- "consistency_rate": 0.9688,
251
- "consistency_first_disagree": 23,
252
- "cpu_baseline_prefill_tok_s": 23.36,
253
- "cpu_baseline_decode_tok_s": 11.69,
254
- "llamaCppCommit": null,
255
- "llamaCppDescribe": null,
256
- "dawnTag": null,
257
- "submittedBy": {
258
- "name": "abhijitramesh",
259
- "hubId": "5fe0b7319126717e4c356efb",
260
- "avatarUrl": "https://cdn-avatars.huggingface.co/v1/production/uploads/5fe0b7319126717e4c356efb/iAaiUJpDmv1nBN3_ZNGVU.jpeg"
261
- },
262
- "iterations": 5
263
- },
264
- {
265
- "machineSlug": "apple-metal-3-4gb-darwin",
266
- "timestamp": "2026-04-25T21:15:00.076Z",
267
- "browser": "chromium-147",
268
- "model": "Qwen3-0.6B",
269
- "repo": "unsloth/Qwen3-0.6B-GGUF",
270
- "variant": "Q4_1",
271
- "filename": "Qwen3-0.6B-Q4_1.gguf",
272
- "sizeMB": 390.14,
273
- "status": "done",
274
- "error": null,
275
- "buildType": "jspi",
276
- "webgpuAvailable": true,
277
- "nGpuLayers": 999,
278
- "wallTimeMs": 77587.89999997616,
279
- "prefill_tok_s": 157.43,
280
- "decode_tok_s": 73.45,
281
- "n_p_eval": 30,
282
- "t_p_eval_ms": 221.3,
283
- "n_eval": 127,
284
- "t_eval_ms": 1728.4,
285
- "consistency_rate": 0.9688,
286
- "consistency_first_disagree": 32,
287
- "cpu_baseline_prefill_tok_s": 6.21,
288
- "cpu_baseline_decode_tok_s": 5.23,
289
- "llamaCppCommit": null,
290
- "llamaCppDescribe": null,
291
- "dawnTag": null,
292
- "submittedBy": {
293
- "name": "abhijitramesh",
294
- "hubId": "5fe0b7319126717e4c356efb",
295
- "avatarUrl": "https://cdn-avatars.huggingface.co/v1/production/uploads/5fe0b7319126717e4c356efb/iAaiUJpDmv1nBN3_ZNGVU.jpeg"
296
- },
297
- "iterations": 5
298
- },
299
- {
300
- "machineSlug": "apple-metal-3-8gb-darwin",
301
- "timestamp": "2026-04-24T07:21:54.498Z",
302
- "browser": "chromium-147",
303
- "model": "Llama-3.2-1B-Instruct",
304
- "repo": "unsloth/Llama-3.2-1B-Instruct-GGUF",
305
- "variant": "Q4_1",
306
- "filename": "Llama-3.2-1B-Instruct-Q4_1.gguf",
307
- "sizeMB": 793.21,
308
- "status": "done",
309
- "error": null,
310
- "buildType": "jspi",
311
- "webgpuAvailable": true,
312
- "nGpuLayers": 999,
313
- "wallTimeMs": 121113.60000002384,
314
- "prefill_tok_s": 141.19,
315
- "decode_tok_s": 58.63,
316
- "n_p_eval": 31,
317
- "t_p_eval_ms": 410.4,
318
- "n_eval": 127,
319
- "t_eval_ms": 2188.4,
320
- "consistency_rate": 0.9922,
321
- "consistency_first_disagree": 100,
322
- "cpu_baseline_prefill_tok_s": 3.04,
323
- "cpu_baseline_decode_tok_s": 2.62,
324
- "llamaCppCommit": null,
325
- "llamaCppDescribe": null,
326
- "dawnTag": null,
327
- "submittedBy": null,
328
- "iterations": 5
329
- },
330
- {
331
- "machineSlug": "apple-metal-3-8gb-darwin",
332
- "timestamp": "2026-04-25T18:38:18.454Z",
333
- "browser": "chromium-147",
334
- "model": "Qwen3-0.6B",
335
- "repo": "unsloth/Qwen3-0.6B-GGUF",
336
- "variant": "BF16",
337
- "filename": "Qwen3-0.6B-BF16.gguf",
338
- "sizeMB": 1142.68,
339
- "status": "done",
340
- "error": null,
341
- "buildType": "jspi",
342
- "webgpuAvailable": true,
343
- "nGpuLayers": 999,
344
- "wallTimeMs": 562839.5,
345
- "prefill_tok_s": 2.92,
346
- "decode_tok_s": 1.84,
347
- "n_p_eval": 30,
348
- "t_p_eval_ms": 10280.8,
349
- "n_eval": 127,
350
- "t_eval_ms": 67368.9,
351
- "consistency_rate": 1,
352
- "consistency_first_disagree": -1,
353
- "cpu_baseline_prefill_tok_s": 3.14,
354
- "cpu_baseline_decode_tok_s": 2.24,
355
- "llamaCppCommit": null,
356
- "llamaCppDescribe": null,
357
- "dawnTag": null,
358
- "submittedBy": {
359
- "name": "abhijitramesh",
360
- "hubId": "5fe0b7319126717e4c356efb",
361
- "avatarUrl": "https://cdn-avatars.huggingface.co/v1/production/uploads/5fe0b7319126717e4c356efb/iAaiUJpDmv1nBN3_ZNGVU.jpeg"
362
- },
363
- "iterations": 5
364
- }
365
- ]
366
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
js/data.js CHANGED
@@ -1,57 +1,71 @@
1
- import { fetchRecentRuns } from './dataset.js';
2
  import { HF_DATASET_REPO } from './run/config.js';
3
 
 
4
  let cachedData = null;
 
 
 
 
 
5
 
6
  export async function loadData() {
7
  if (cachedData) return cachedData;
8
 
9
- // Static baseline — pre-built by CI from the dataset on the last code push.
10
- const baselineResp = await fetch('data/combined.json');
11
- const baseline = await baselineResp.json();
 
 
12
 
13
- // Live delta pull recent submissions from the HF dataset that landed
14
- // since baseline.meta.generatedAt. Best-effort: a CORS / network / parse
15
- // failure here just leaves the dashboard on the static baseline rather
16
- // than blocking the whole page.
17
  try {
18
- const since = baseline.meta?.generatedAt;
19
- const { records, machines, fileCount } = await fetchRecentRuns(HF_DATASET_REPO, since);
20
  if (fileCount > 0) {
21
- mergeLiveDelta(baseline, records, machines);
22
  }
 
 
23
  } catch (err) {
24
- console.warn(`Live dataset sync skipped: ${err.message}`);
 
25
  }
26
-
27
- cachedData = baseline;
28
  return cachedData;
29
  }
30
 
31
- /* Append fresh records into the baseline and recompute the meta lookups so
32
- the dashboard's filters/charts see them as first-class data. Records that
33
- already exist in the baseline (deduped by a composite key) are dropped —
34
- if CI ran recently, the static combined.json already contains them. */
35
- function mergeLiveDelta(baseline, records, machines) {
36
- const baselineKeys = new Set(baseline.results.map(keyOf));
37
- const fresh = records.filter(r => !baselineKeys.has(keyOf(r)));
38
- if (fresh.length === 0) return;
 
 
 
 
 
 
 
 
 
39
 
40
- baseline.results.push(...fresh);
41
 
42
- // meta.models / meta.browsers union.
43
- const modelsSet = new Set(baseline.meta.models || []);
44
- const browsersSet = new Set(baseline.meta.browsers || []);
45
- for (const r of fresh) {
46
  if (r.model) modelsSet.add(r.model);
47
  if (r.browser) browsersSet.add(r.browser);
48
  }
49
- baseline.meta.models = [...modelsSet].sort();
50
- baseline.meta.browsers = [...browsersSet].sort();
51
 
52
- // meta.machines: keep existing entries, add any new slugs from the live
53
- // delta, then recompute resultCount/passCount across baseline+fresh.
54
- const machineMap = new Map((baseline.meta.machines || []).map(m => [m.slug, m]));
55
  for (const m of machines) {
56
  if (!machineMap.has(m.slug)) machineMap.set(m.slug, { ...m });
57
  }
@@ -59,12 +73,12 @@ function mergeLiveDelta(baseline, records, machines) {
59
  m.resultCount = 0;
60
  m.passCount = 0;
61
  }
 
62
  // Per-machine submitter aggregation — counts contributions and tracks the
63
- // most recent submission so the dashboard can render a stacked-avatar row
64
- // sorted by activity. Mirrors scripts/build-site.js logic so live and
65
- // baseline data stay byte-equivalent.
66
  const submitterAccumulator = new Map(); // slug → Map(key → {profile, count, latestAt})
67
- for (const r of baseline.results) {
68
  const m = machineMap.get(r.machineSlug);
69
  if (!m) continue;
70
  m.resultCount += 1;
@@ -92,8 +106,26 @@ function mergeLiveDelta(baseline, records, machines) {
92
  .map(({ profile, count, latestAt }) => ({ ...profile, count, latestAt }))
93
  .sort((a, b) => b.count - a.count || (b.latestAt || '').localeCompare(a.latestAt || ''));
94
  }
95
- baseline.meta.machines = [...machineMap.values()];
96
- baseline.meta.generatedAt = new Date().toISOString();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
  }
98
 
99
  /* Reduce a flat result set down to one canonical row per
@@ -123,13 +155,6 @@ export function selectBestResults(records) {
123
  return [...bestByCell.values()];
124
  }
125
 
126
- /* Composite key for dedupe. The submit pipeline writes one record per
127
- (machine, browser, model, variant, timestamp) tuple, so this is unique
128
- in practice. */
129
- function keyOf(r) {
130
- return `${r.machineSlug}|${r.browser}|${r.model}|${r.variant}|${r.timestamp}`;
131
- }
132
-
133
  export function filterResults(results, filters) {
134
  return results.filter(r => {
135
  if (filters.machine && filters.machine !== 'all' && r.machineSlug !== filters.machine) return false;
 
1
+ import { fetchAllRuns } from './dataset.js';
2
  import { HF_DATASET_REPO } from './run/config.js';
3
 
4
+ // In-memory cache for the current page session.
5
  let cachedData = null;
6
+ // sessionStorage cache so a refresh-within-a-minute doesn't re-fetch the
7
+ // entire dataset. Short TTL — submissions land continuously and the
8
+ // dashboard is the surface where we actually want freshness.
9
+ const SESSION_CACHE_KEY = 'webgpu-bench:dashboard-data';
10
+ const SESSION_CACHE_TTL_MS = 60 * 1000;
11
 
12
  export async function loadData() {
13
  if (cachedData) return cachedData;
14
 
15
+ const fromSession = readSessionCache();
16
+ if (fromSession) {
17
+ cachedData = fromSession;
18
+ return cachedData;
19
+ }
20
 
21
+ // Single source of truth: the HF dataset repo. No static baseline. A new
22
+ // dashboard with zero submissions shows an empty state until something is
23
+ // submitted.
24
+ const empty = makeEmptyDataset();
25
  try {
26
+ const { records, machines, fileCount } = await fetchAllRuns(HF_DATASET_REPO);
 
27
  if (fileCount > 0) {
28
+ mergeRecords(empty, records, machines);
29
  }
30
+ cachedData = empty;
31
+ writeSessionCache(cachedData);
32
  } catch (err) {
33
+ console.warn(`Live dataset load failed: ${err.message}`);
34
+ cachedData = empty;
35
  }
 
 
36
  return cachedData;
37
  }
38
 
39
+ function makeEmptyDataset() {
40
+ return {
41
+ meta: {
42
+ machines: [],
43
+ models: [],
44
+ browsers: [],
45
+ generatedAt: new Date().toISOString(),
46
+ },
47
+ results: [],
48
+ };
49
+ }
50
+
51
+ /* Append records into an empty payload and recompute the meta lookups. Same
52
+ shape the old combined.json had, so all downstream consumers (charts,
53
+ tables, machine cards) work unchanged. */
54
+ function mergeRecords(payload, records, machines) {
55
+ if (records.length === 0) return;
56
 
57
+ payload.results.push(...records);
58
 
59
+ const modelsSet = new Set(payload.meta.models || []);
60
+ const browsersSet = new Set(payload.meta.browsers || []);
61
+ for (const r of records) {
 
62
  if (r.model) modelsSet.add(r.model);
63
  if (r.browser) browsersSet.add(r.browser);
64
  }
65
+ payload.meta.models = [...modelsSet].sort();
66
+ payload.meta.browsers = [...browsersSet].sort();
67
 
68
+ const machineMap = new Map((payload.meta.machines || []).map(m => [m.slug, m]));
 
 
69
  for (const m of machines) {
70
  if (!machineMap.has(m.slug)) machineMap.set(m.slug, { ...m });
71
  }
 
73
  m.resultCount = 0;
74
  m.passCount = 0;
75
  }
76
+
77
  // Per-machine submitter aggregation — counts contributions and tracks the
78
+ // most-recent submission so the machine card can render a stacked-avatar
79
+ // row sorted by activity.
 
80
  const submitterAccumulator = new Map(); // slug → Map(key → {profile, count, latestAt})
81
+ for (const r of payload.results) {
82
  const m = machineMap.get(r.machineSlug);
83
  if (!m) continue;
84
  m.resultCount += 1;
 
106
  .map(({ profile, count, latestAt }) => ({ ...profile, count, latestAt }))
107
  .sort((a, b) => b.count - a.count || (b.latestAt || '').localeCompare(a.latestAt || ''));
108
  }
109
+ payload.meta.machines = [...machineMap.values()];
110
+ payload.meta.generatedAt = new Date().toISOString();
111
+ }
112
+
113
+ function readSessionCache() {
114
+ try {
115
+ const raw = sessionStorage.getItem(SESSION_CACHE_KEY);
116
+ if (!raw) return null;
117
+ const { ts, data } = JSON.parse(raw);
118
+ if (typeof ts !== 'number' || (Date.now() - ts) > SESSION_CACHE_TTL_MS) return null;
119
+ return data;
120
+ } catch {
121
+ return null;
122
+ }
123
+ }
124
+
125
+ function writeSessionCache(data) {
126
+ try {
127
+ sessionStorage.setItem(SESSION_CACHE_KEY, JSON.stringify({ ts: Date.now(), data }));
128
+ } catch { /* quota or disabled */ }
129
  }
130
 
131
  /* Reduce a flat result set down to one canonical row per
 
155
  return [...bestByCell.values()];
156
  }
157
 
 
 
 
 
 
 
 
158
  export function filterResults(results, filters) {
159
  return results.filter(r => {
160
  if (filters.machine && filters.machine !== 'all' && r.machineSlug !== filters.machine) return false;
js/dataset.js CHANGED
@@ -20,9 +20,12 @@ const HF = 'https://huggingface.co';
20
  // dedupe out anyway.
21
  const CLOCK_SKEW_MS = 10 * 60 * 1000;
22
 
23
- // Cap on parallel/total file fetches per dashboard load. 50 covers ~weeks
24
- // of submissions before CI rebuilds; beyond that we silently truncate.
25
- const MAX_FETCH = 50;
 
 
 
26
 
27
  /* Fetch the runs/ tree from the dataset. Returns the file entries that
28
  look newer than `sinceISO` (with a clock-skew buffer applied). On any
@@ -61,12 +64,20 @@ async function fetchRunFile(datasetRepo, filePath) {
61
  return resp.json();
62
  }
63
 
 
 
 
 
 
 
 
64
  /* List the dataset tree and download every file that's newer than the
65
- baseline's generatedAt. Returns flattened records ready to append to
66
- combined.results, plus the raw machine info per file so the merge can
67
- keep meta.machines accurate. */
68
  export async function fetchRecentRuns(datasetRepo, sinceISO) {
69
- const files = await listRecentRunFiles(datasetRepo, sinceISO);
 
 
 
70
  if (files.length === 0) return { records: [], machines: [], fileCount: 0 };
71
 
72
  const records = [];
 
20
  // dedupe out anyway.
21
  const CLOCK_SKEW_MS = 10 * 60 * 1000;
22
 
23
+ // Cap on parallel/total file fetches per dashboard load. The dashboard now
24
+ // pulls the entire dataset live (no static baseline), so this cap is the
25
+ // upper bound on how many run files the page will download at once. 1000
26
+ // is conservative — actual bench submissions are typically ≤ 1 KB each so
27
+ // the bandwidth ceiling is well under a megabyte even at the cap.
28
+ const MAX_FETCH = 1000;
29
 
30
  /* Fetch the runs/ tree from the dataset. Returns the file entries that
31
  look newer than `sinceISO` (with a clock-skew buffer applied). On any
 
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
 
83
  const records = [];