Files
storage/benchmarks/index.html
2023-09-26 08:40:32 +02:00

374 lines
12 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=yes"/>
<style>
html {
font-family: BlinkMacSystemFont, -apple-system, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
background-color: #fff;
font-size: 16px;
}
body {
color: #4a4a4a;
margin: 8px;
font-size: 1em;
font-weight: 400;
}
header {
margin-bottom: 8px;
display: flex;
flex-direction: column;
}
main {
width: 100%;
display: flex;
flex-direction: column;
}
a {
color: #3273dc;
cursor: pointer;
text-decoration: none;
}
a:hover {
color: #000;
}
button {
color: #fff;
background-color: #3298dc;
border-color: transparent;
cursor: pointer;
text-align: center;
}
button:hover {
background-color: #2793da;
flex: none;
}
.switch-light span {
max-width: 100px;
}
.spacer {
flex: auto;
}
.small {
font-size: 0.75rem;
}
footer {
margin-top: 16px;
display: flex;
align-items: center;
}
.header-label {
margin-right: 4px;
}
.benchmark-set {
margin: 8px 0;
width: 100%;
display: flex;
flex-direction: column;
}
.benchmark-title {
font-size: 3rem;
font-weight: 600;
word-break: break-word;
text-align: center;
}
.benchmark-graphs {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
flex-wrap: wrap;
width: 100%;
}
.benchmark-chart {
max-width: 33%;
max-height: 500px;
}
@media only screen and (max-width: 900px) {
.benchmark-chart {
max-width: 50%;
}
}
@media only screen and (max-width: 700px) {
.benchmark-chart {
max-width: 100%;
max-height: 100%;
}
}
</style>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/css-toggle-switch@latest/dist/toggle-switch.css" />
<title>Benchmarks</title>
</head>
<body>
<header id="header">
<div class="header-item">
<strong class="header-label">Last Update:</strong>
<span id="last-update"></span>
</div>
<div class="header-item">
<strong class="header-label">Repository:</strong>
<a id="repository-link" rel="noopener"></a>
</div>
</header>
<label class="switch-light switch-candy" onclick="">
<input type="checkbox" checked>
<strong>
Grouping
</strong>
<span>
<span>Off</span>
<span>On</span>
<a></a>
</span>
</label>
<main id="main"></main>
<footer>
<button id="dl-button">Download data as JSON</button>
<div class="spacer"></div>
<div class="small">Powered by <a rel="noopener" href="https://github.com/marketplace/actions/continuous-benchmark">github-action-benchmark</a>
</div>
</footer>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script src="data.js"></script>
<script id="main-script">
'use strict';
(function () {
// Colors from https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
const colors = ['#00add8', '#dea584', '#f1e05a', '#000080', '#3572a5', '#f34b7d', '#a270ba', '#b07219', '#178600', '#38ff38', '#ff3838', '#333333', '#800000', '#FF5733', '#33FF57', '#E833FF', '#FF5733', '#5733FF', '#33A6FF', '#FF33E3', '#ff8133', '#FFFF33', '#33FFFF', '#FF3333', '#33FF33', '#3333FF'];
function addBench(map, name, result) {
const arr = map.get(name);
if (arr === undefined) {
map.set(name, [result]);
} else {
arr.push(result);
}
}
function collectBenchesPerTestCase(entries, grouping) {
const map = new Map();
for (const entry of entries) {
const {commit, date, tool, benches} = entry;
for (const bench of benches) {
const result = {commit, date, tool, bench};
if (grouping && pkgRegEx.test(bench.name)) {
const pkgName = bench.name.match(pkgRegEx)[1];
bench.name = bench.name.replace(pkgRegEx, '_');
const pkgMap = map.get(bench.name) || new Map();
map.set(bench.name, pkgMap);
addBench(pkgMap, pkgName, result);
} else {
addBench(map, bench.name, result);
}
}
}
return map;
}
function init(packages) {
const data = window.BENCHMARK_DATA;
// make a copy of the original data
let dataEntries = JSON.parse(JSON.stringify(data.entries));
dataEntries.Benchmark = dataEntries.Benchmark.map((item) => {
item.benches = item.benches.filter((benchData) => benchData.unit.includes('ns/op'));
return item;
});
// Render header
document.getElementById('last-update').textContent = new Date(data.lastUpdate).toString();
const repoLink = document.getElementById('repository-link');
repoLink.href = data.repoUrl;
repoLink.textContent = data.repoUrl;
// Render footer
document.getElementById('dl-button').onclick = () => {
const dataUrl = 'data:,' + JSON.stringify(data, null, 2);
const a = document.createElement('a');
a.href = dataUrl;
a.download = 'benchmark_data.json';
a.click();
};
// Prepare data points for charts
return Object.keys(dataEntries).map(name => ({
name,
dataSet: collectBenchesPerTestCase(dataEntries[name], window.grouping),
}));
}
function fetchPackageNames(repoUrl) {
// GitHub Repository-URL
repoUrl = repoUrl.replace('github.com', 'api.github.com/repos') + '/contents';
// Fetch-Anfrage, um die Repository-Inhalte abzurufen
return fetch(repoUrl, {method: 'GET'})
.then(response => response.json())
.then(data => {
return data.filter(item => item.type === 'dir' && item.name !== '.github').map((item => item.name));
})
.catch(error => {
console.error('Fehler beim Abrufen der Daten:', error);
});
}
function toDataSet(name, dataset, color) {
return {
label: name,
data: dataset.map(d => d.bench.value),
borderColor: color,
backgroundColor: color + '10', // Add alpha for #rrggbbaa
fill: true,
};
}
function getColorForName(name) {
const pkgName = name.match(pkgRegEx)?.[1] || name;
let colorIndex = window.packages.findIndex((p) => p.toLowerCase() === pkgName.toLowerCase());
if (colorIndex === -1) {
colorIndex = 0;
}
return colors[colorIndex];
}
function renderGraph(parent, name, dataset) {
const canvas = document.createElement('canvas');
canvas.className = 'benchmark-chart';
parent.appendChild(canvas);
let dataList = [];
const isPackageDataSet = dataset instanceof Map;
if (dataset instanceof Map) {
let i = 0;
for (const [packageName, packageDataSet] of dataset.entries()) {
dataList.push(toDataSet(packageName, packageDataSet, getColorForName(packageName)));
++i;
}
dataset = Array.from(dataset)?.[0]?.[1] || [];
} else if (Array.isArray(dataset)) {
dataList.push(toDataSet(name, dataset, getColorForName(name)));
}
const data = {labels: dataset.map(d => d.commit.id.slice(0, 7)), datasets: dataList};
const options = {
onResize: (chart, newSize) => {
chart.options.plugins.legend.display = window.screen.width < 450 ? dataList.length === 1 : true;
chart.update();
},
plugins: {
title: {
display: isPackageDataSet,
text: name,
},
legend: {
display: window.screen.width < 450 ? dataList.length === 1 : true,
},
scales: {
x: {
title: {
display: true,
text: 'commit',
},
},
y: {
title: {
display: true,
text: dataset.length > 0 ? dataset[0].bench.unit : '',
},
beginAtZero: true,
},
},
tooltip: {
callbacks: {
title: (context) => {
const index = context[0].dataIndex;
const data = dataset[index];
return [data.commit.message, data.commit.timestamp + ' committed by @' + data.commit.committer.username];
},
label: (context) => {
const {range, unit} = dataset[context.dataIndex].bench;
const value = context.dataset.data[context.dataIndex];
let label = [context.dataset.label, value, unit].filter(Boolean).join(' ');
if (range) {
label += ' (' + range + ')';
}
return label;
},
},
},
},
};
new Chart(canvas, {
type: 'line',
data,
options,
});
}
function renderBenchSet(name, benchSet, main) {
const setElem = document.createElement('div');
setElem.className = 'benchmark-set';
main.appendChild(setElem);
const nameElem = document.createElement('h1');
nameElem.className = 'benchmark-title';
nameElem.textContent = name;
setElem.appendChild(nameElem);
const graphsElem = document.createElement('div');
graphsElem.className = 'benchmark-graphs';
setElem.appendChild(graphsElem);
for (const [benchName, benches] of benchSet.entries()) {
renderGraph(graphsElem, benchName, benches);
}
}
function renderAllChars(dataSets) {
const main = document.getElementById('main');
main.innerHTML = '';
for (const {name, dataSet} of dataSets) {
renderBenchSet(name, dataSet, main);
}
}
window.grouping = true;
fetchPackageNames(window.BENCHMARK_DATA.repoUrl).then((packages) => {
window.packages = packages;
window.pkgRegEx = new RegExp('_(' + packages.join('|') + ')(/|_)', 'i');
renderAllChars(init(window.packages)); // Start
});
document.querySelector('.switch-light').addEventListener('click', (event) => {
window.grouping = event.currentTarget.querySelector('input').checked;
renderAllChars(init(window.packages));
});
})();
</script>
</body>
</html>