Skip to content

Instantly share code, notes, and snippets.

@vietj
Created April 16, 2024 15:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vietj/2346d2216ee120fc2464257c721c4eac to your computer and use it in GitHub Desktop.
Save vietj/2346d2216ee120fc2464257c721c4eac to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Perflab results</title>
<style>
body {
font-family: monospace;
font-size: 12pt;
}
em {
font-style: italic;
}
nav a {
color: blue;
}
nav a:visited {
color: blue;
}
div.table {
overflow-x: auto;
}
table {
border: 1px solid;
border-collapse: collapse;
border-spacing: 0;
table-layout: fixed;
word-wrap: break-word;
caption-side: bottom;
font-size: 10pt;
}
th {
border: 1px solid;
width: 100px;
}
td {
border: 1px solid;
text-align: right;
}
caption {
margin-top: 1em;
font-style: italic;
}
div#chart {
width: 1400px;
height: 1000px;
}
</style>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/handlebars@latest/dist/handlebars.js"></script>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="application/javascript">
function round(num) {
return Math.round((num + Number.EPSILON) * 100) / 100
}
function average(values) {
let total = 0;
for (const value of values) {
total += value;
}
return round(total / values.length);
}
function standardDeviation(values, average) {
let total = 0;
for (const value of values) {
total += (value - average) * (value - average);
}
return round(Math.sqrt(total / (values.length - 1)));
}
function compileTemplate(hb, id) {
return hb.compile(document.querySelector(id).innerHTML);
}
</script>
</head>
<body>
<script id="title-template" type="text/x-handlebars">
<h1><em>{{benchmark}}</em> benchmark results</h1>
</script>
<script id="nav-template" type="text/x-handlebars">
<h2>Summary</h2>
<ul>
{{#each branches}}
<li><a href="#{{this}}">Results for branch <em>{{this}}</em></a></li>
{{/each}}
<li><a href="#chart">Chart</a></li>
</ul>
</script>
<script id="table-template" type="text/x-handlebars">
<h3>Results for branch <em>{{branch}}</em></h3>
<table>
<caption>{{branch}} - {{benchmark}}</caption>
<thead>
<tr>
<th>&nbsp;</th>
{{#each iterations}}
{{#if @first}}
{{#each values}}
<th>{{inc @index}}</th>
{{/each}}
{{/if}}
{{/each}}
<th>Avg</th>
<th>Stddev</th>
<th>Rel Stddev</th>
<th>Min</th>
<th>Max</th>
</tr>
</thead>
<tbody>
{{#each iterations}}
<tr>
<th>{{concurrency}}</th>
{{#each values}}
<td>{{this}}</td>
{{/each}}
<td>{{avg}}</td>
<td>{{stddev}}</td>
<td>{{relstddev}}%</td>
<td>{{min}}</td>
<td>{{max}}</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
<script id="chart-template" type="text/x-handlebars">
<h3><em>{{benchmark}}</em> benchmark results chart</h3>
</script>
<script id="results" type="application/json">
{
"benchmark" : "plaintext",
"data" : [
{
"branch" : "master",
"iterations" : [
{
"concurrency" : 256,
"values" : [
2717823.84,
2680900.62,
2834154.65,
2822660.49,
2763843.48
]
},
{
"concurrency" : 1024,
"values" : [
3886914.44,
3806632.68,
3984644.54,
3884575.89,
3893709.51
]
},
{
"concurrency" : 4096,
"values" : [
3568927.77,
3521350.55,
3646832.78,
3571265.94,
3570175.43
]
},
{
"concurrency" : 16384,
"values" : [
3487497.39,
3414334.9,
3559566.4,
3460868.2,
3477708.49
]
}
]
},
{
"branch" : "5.0.0",
"iterations" : [
{
"concurrency" : 256,
"values" : [
2782955.43,
2782265.72,
2796669.31,
2845717.83,
2771676.11
]
},
{
"concurrency" : 1024,
"values" : [
3961027.26,
4044993.59,
3991643.94,
4042334.87,
4068311.87
]
},
{
"concurrency" : 4096,
"values" : [
3593911.16,
3644677,
3612948.09,
3671314.32,
3677518.86
]
},
{
"concurrency" : 16384,
"values" : [
3480724.2,
3539569,
3499226.36,
3569931.28,
3563795.52
]
}
]
},
{
"branch" : "5.0.0-irq",
"iterations" : [
{
"concurrency" : 256,
"values" : [
2746501.12,
2793852.32,
2774738.9,
2811320.15,
2759195.45
]
},
{
"concurrency" : 1024,
"values" : [
3902486.55,
3910620.32,
3963643.23,
3891527.89,
3819470.98
]
},
{
"concurrency" : 4096,
"values" : [
3537508.54,
3545438.32,
3582421.56,
3513261.94,
3506738.52
]
},
{
"concurrency" : 16384,
"values" : [
3428823.9,
3406955.68,
3465452.75,
3391839.08,
3351054
]
}
]
},
{
"branch" : "5.0.0-irq-nv",
"iterations" : [
{
"concurrency" : 256,
"values" : [
2753123.51,
2781986.17,
2796474.94,
2771636.46,
2727542.22
]
},
{
"concurrency" : 1024,
"values" : [
3897938.11,
3905934.28,
3998845.05,
3919390.44,
3916317.9
]
},
{
"concurrency" : 4096,
"values" : [
3508418.39,
3548539.05,
3598742.27,
3556476.15,
3563416.93
]
},
{
"concurrency" : 16384,
"values" : [
3350382.42,
3418825.73,
3499487.36,
3409351.06,
3423549.94
]
}
]
}
]
}
</script>
<script id="results-sample" type="application/json">
{
"benchmark" : "plaintext",
"data" : [
{
"branch" : "oct22-4.1.4",
"iterations" : [
{
"concurrency" : 256,
"values" : [
156727760,
155759616,
157254816,
156559792,
159958480,
158659072,
158183968,
159137296,
165708144,
164706752
]
},
{
"concurrency" : 1024,
"values" : [
199564272,
197151808,
194545232,
193772416,
198594704,
198366976,
196662720,
195458960,
196324768,
192449888
]
},
{
"concurrency" : 4096,
"values" : [
193034144,
189667440,
186151984,
186435504,
192040944,
192837712,
188253760,
187313312,
189127824,
184370528
]
},
{
"concurrency" : 16384,
"values" : [
185129104,
183016688,
179138992,
180670160,
184818832,
183895152,
181635008,
181818768,
182377568,
177928880
]
}
]
},
{
"branch" : "oct22-4.3.3",
"iterations" : [
{
"concurrency" : 256,
"values" : [
160214704,
155017760,
160644512,
156656080,
161479200,
162079344,
157070352,
160220640,
157914496,
156130368
]
},
{
"concurrency" : 1024,
"values" : [
191760816,
193519840,
189691824,
190042272,
194549120,
189168112,
186736704,
189591728,
198427296,
189589936
]
},
{
"concurrency" : 4096,
"values" : [
184101344,
185671952,
182230672,
182944592,
186202864,
182178928,
180546960,
182449008,
190922912,
183281776
]
},
{
"concurrency" : 16384,
"values" : [
178642224,
178672128,
176392016,
176981712,
180903232,
176566112,
174267152,
176784800,
183117024,
176189008
]
}
]
},
{
"branch" : "oct22-4.3.4",
"iterations" : [
{
"concurrency" : 256,
"values" : [
157115008,
156171248,
160244336,
157100896,
158777696,
159395344,
162272144,
160066992,
160840400,
161439840
]
},
{
"concurrency" : 1024,
"values" : [
194645280,
185893600,
190015376,
194778352,
185906096,
189741680,
193831760,
200660512,
194202848,
192093808
]
},
{
"concurrency" : 4096,
"values" : [
185596816,
179253616,
182262128,
186692976,
179245056,
182426032,
185597136,
193070048,
186618320,
184398240
]
},
{
"concurrency" : 16384,
"values" : [
179799536,
173211018,
177589328,
180694416,
172679936,
175337776,
180338800,
183618800,
180874704,
179009472
]
}
]
}
]
}
</script>
<script type="application/javascript">
let resultsText = document.querySelector("#results").innerHTML;
if (resultsText.trim().length === 0) {
resultsText = document.querySelector("#results-sample").innerHTML;
}
const results = JSON.parse(resultsText);
const branches = results.data.map(d => d.branch);
for (const data of results.data) {
for (const iteration of data.iterations) {
iteration.avg = average(iteration.values);
iteration.stddev = standardDeviation(iteration.values, iteration.avg);
iteration.relstddev = round(100 * (iteration.stddev / iteration.avg));
iteration.min = Math.min(...iteration.values);
iteration.max = Math.max(...iteration.values);
}
}
Handlebars.registerHelper("inc", value => parseInt(value) + 1);
document.title = `${results.benchmark} benchmark results`
const titleTemplateFunc = compileTemplate(Handlebars, "#title-template");
const titleElem = document.createElement("div");
titleElem.innerHTML = titleTemplateFunc({benchmark: results.benchmark});
document.body.appendChild(titleElem);
const navTemplateFunc = compileTemplate(Handlebars, "#nav-template");
const navElem = document.createElement("nav");
navElem.innerHTML = navTemplateFunc({branches: branches});
document.body.appendChild(navElem);
const tableTemplateFunc = compileTemplate(Handlebars, "#table-template");
for (const data of results.data) {
const tableElem = document.createElement("div");
tableElem.id = data.branch;
tableElem.className = "table";
tableElem.innerHTML = tableTemplateFunc({benchmark: results.benchmark, ...data});
document.body.appendChild(tableElem);
}
const chartTemplateFunc = compileTemplate(Handlebars, "#chart-template");
const chartElem = document.createElement("div");
chartElem.innerHTML = chartTemplateFunc({benchmark: results.benchmark});
const charTarget = document.createElement("div");
charTarget.id = "chart";
chartElem.appendChild(charTarget);
document.body.appendChild(chartElem);
google.charts.load("current", {"packages": ["corechart"]});
google.charts.setOnLoadCallback(function () {
const dataTable = new google.visualization.DataTable();
dataTable.addColumn("string", "Concurrency");
for (const branch of branches) {
dataTable.addColumn("number", branch);
for (let i = 0; i < results.data[0].iterations[0].values.length; i++) {
dataTable.addColumn({id: `value${i.toString()}`, type: "number", role: "interval"});
}
}
for (let i = 0; i < results.data[0].iterations.length; i++) {
const row = [];
for (const data of results.data) {
const iteration = data.iterations[i];
if (row.length === 0) {
row.push(iteration.concurrency.toString());
}
row.push(iteration.avg);
const sorted = new Array(...iteration.values).sort((a,b) => a-b);
row.push(...sorted);
}
dataTable.addRow(row);
}
const options = {
title: `Throughput in '${results.benchmark}' benchmark`,
vAxis: {
viewWindowMode: "explicit",
viewWindow: {min: 0},
title: "Requests/sec"
},
hAxis: {
title: "Concurrency"
},
intervals: {style: "bars", color: "#333333"},
fontName: "monospace"
};
const chart = new google.visualization.ColumnChart(document.getElementById("chart"));
google.visualization.events.addListener(chart, "ready", function() {
const div = document.createElement("div");
div.innerHTML = `<img src="${chart.getImageURI()}">`;
chartElem.appendChild(div);
});
chart.draw(dataTable, options);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment