-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
106 lines (97 loc) · 5.07 KB
/
Copy pathindex.html
File metadata and controls
106 lines (97 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Hindsight Performance</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://rsms.me/">
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/style.css">
</head>
<body class="bg-gray-50 text-gray-900">
<header id="page-header" class="bg-white border-b border-gray-200 px-6 py-3"></header>
<main id="main" class="max-w-7xl mx-auto px-6 py-8"></main>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script type="module">
import {
loadRecentRuns, renderHeader, renderPageHeading, renderLatestBanner, renderRunsTable,
timeSeries, lineChart, makeDataset, fmtNumber, renderDelta, median,
filterByScale, runsSummary,
SUITES, SUITE_LABELS, SUITE_HEADLINE, getSuite, escapeHtml,
} from './assets/app.js';
document.getElementById('page-header').innerHTML = renderHeader('overview');
const main = document.getElementById('main');
(async () => {
let payload;
try {
payload = await loadRecentRuns(60);
} catch (e) {
main.innerHTML = `<div class="text-center py-16 text-gray-500">Failed to load data: ${escapeHtml(e.message)}</div>`;
return;
}
const { manifest, runs } = payload;
if (runs.length === 0) {
main.innerHTML = '<div class="text-center py-16 text-gray-500">No perf runs yet — waiting for the first one to land.</div>';
return;
}
const latest = runs[0];
// Compare like-with-like: charts + deltas use only the latest run's scale.
const { runs: scaled, scale, hidden } = filterByScale(runs, latest.scale);
const cards = SUITES.map((suite, idx) => {
const headline = SUITE_HEADLINE[suite];
const latestSuite = getSuite(latest, suite);
const curr = latestSuite ? headline.get(latestSuite) : null;
const histPts = timeSeries(scaled.slice(1), suite, headline.get);
const baseline = median(histPts.map(p => p.y));
const n = histPts.length;
const points = timeSeries(scaled, suite, headline.get);
return `
<div class="bg-white border border-gray-200 rounded-lg p-5 min-w-0">
<div class="flex items-baseline justify-between mb-2 gap-2">
<h3 class="text-xs uppercase tracking-wide text-gray-500 font-semibold m-0 truncate">${SUITE_LABELS[suite]}</h3>
<a class="text-xs text-blue-600 hover:underline whitespace-nowrap" href="${suite}.html">Details →</a>
</div>
<div class="flex items-baseline gap-2 flex-wrap">
<span class="text-3xl font-semibold tabular-nums">${fmtNumber(curr)}</span>
<span class="text-gray-500 text-sm">${headline.unit}</span>
${renderDelta(curr, baseline, headline.biggerIsBetter)}
</div>
<div class="text-gray-400 text-xs mt-1 mb-2">${headline.label} · ${n > 0 ? `vs median of prior ${n} run${n === 1 ? '' : 's'}` : 'no prior runs'}</div>
<div class="chart-container" id="mini-host-${idx}"><canvas id="mini-${idx}"></canvas></div>
<div class="text-[11px] text-gray-400 mt-1 text-right">${points.length} data point${points.length === 1 ? '' : 's'}</div>
</div>
`;
}).join('');
const runsByFile = {};
manifest.runs.slice(0, runs.length).forEach((e, i) => { runsByFile[e.data_file] = runs[i]; });
main.innerHTML = `
${renderPageHeading('Overview · all suites', `Headline metric per suite, trend vs median · ${runsSummary(scaled, scale, hidden)}`)}
${renderLatestBanner(latest)}
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">${cards}</div>
<h2 class="text-base font-semibold mt-8 mb-3">Recent runs <span class="text-gray-400 text-sm font-normal">· all scales</span></h2>
${renderRunsTable(manifest.runs.slice(0, 25), runsByFile)}
`;
SUITES.forEach((suite, idx) => {
const headline = SUITE_HEADLINE[suite];
const points = timeSeries(scaled, suite, headline.get);
const host = document.getElementById('mini-host-' + idx);
if (points.length < 2) {
host.innerHTML = '<div class="flex items-center justify-center h-full text-xs text-gray-400">need 2+ runs</div>';
return;
}
const canvas = document.getElementById('mini-' + idx);
lineChart(canvas, [makeDataset(headline.label, points, idx)], {
unit: headline.unit,
legend: false,
compact: true,
onClick: () => { window.location.href = suite + '.html'; },
});
});
})();
</script>
</body>
</html>