238 lines
9.3 KiB
HTML
238 lines
9.3 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>Benchmark Results Comparison</title>
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<style>
|
|
#graph-container {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
grid-template-rows: repeat(3, 1fr);
|
|
gap: 20px;
|
|
width: 100%;
|
|
height: 600px;
|
|
}
|
|
#graph-container canvas {
|
|
width: 100% !important;
|
|
height: 100% !important;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Benchmark Results Comparison</h1>
|
|
<div>
|
|
<label for="test-name">Test Name:</label>
|
|
<select id="test-name"></select>
|
|
</div>
|
|
<div>
|
|
<label for="config-name-1">Configuration 1:</label>
|
|
<select id="config-name-1"></select>
|
|
</div>
|
|
<div>
|
|
<label for="config-name-2">Configuration 2:</label>
|
|
<select id="config-name-2"></select>
|
|
</div>
|
|
<button id="compare-btn">Compare</button>
|
|
<div id="graph-container"></div>
|
|
<script>
|
|
const testNameSelect = document.getElementById('test-name');
|
|
const configName1Select = document.getElementById('config-name-1');
|
|
const configName2Select = document.getElementById('config-name-2');
|
|
const compareBtn = document.getElementById('compare-btn');
|
|
|
|
// Fetch test names and populate the drop-down
|
|
fetch('/api/test-names')
|
|
.then(response => response.json())
|
|
.then(testNames => {
|
|
testNames.forEach(testName => {
|
|
const option = document.createElement('option');
|
|
option.value = testName;
|
|
option.textContent = testName;
|
|
testNameSelect.appendChild(option);
|
|
});
|
|
|
|
// If there is only one test, select it and populate the configuration names
|
|
if (testNames.length === 1) {
|
|
testNameSelect.value = testNames[0];
|
|
updateConfigNames(testNames[0]);
|
|
}
|
|
});
|
|
|
|
// Update configuration names when a test name is selected
|
|
testNameSelect.addEventListener('change', () => {
|
|
const selectedTestName = testNameSelect.value;
|
|
updateConfigNames(selectedTestName);
|
|
});
|
|
|
|
// Fetch configuration names and populate the drop-downs
|
|
function updateConfigNames(testName) {
|
|
configName1Select.innerHTML = '';
|
|
configName2Select.innerHTML = '';
|
|
|
|
fetch(`/api/config-names?test_name=${testName}`)
|
|
.then(response => response.json())
|
|
.then(configNames => {
|
|
for (const configName in configNames) {
|
|
const runTimes = configNames[configName];
|
|
runTimes.forEach(runTime => {
|
|
const option1 = document.createElement('option');
|
|
option1.value = `${configName}/${runTime}`;
|
|
option1.textContent = `${configName}/${runTime}`;
|
|
configName1Select.appendChild(option1);
|
|
|
|
const option2 = document.createElement('option');
|
|
option2.value = `${configName}/${runTime}`;
|
|
option2.textContent = `${configName}/${runTime}`;
|
|
configName2Select.appendChild(option2);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
// Fetch aggregated data and render graphs when the compare button is clicked
|
|
compareBtn.addEventListener('click', () => {
|
|
const selectedTestName = testNameSelect.value;
|
|
const [selectedConfigName1, selectedRunTime1] = configName1Select.value.split('/');
|
|
const [selectedConfigName2, selectedRunTime2] = configName2Select.value.split('/');
|
|
|
|
Promise.all([
|
|
fetch(`/api/aggregated-data?test_name=${selectedTestName}&config_name=${selectedConfigName1}&run_time=${selectedRunTime1}`),
|
|
fetch(`/api/aggregated-data?test_name=${selectedTestName}&config_name=${selectedConfigName2}&run_time=${selectedRunTime2}`)
|
|
])
|
|
.then(responses => Promise.all(responses.map(response => response.json())))
|
|
.then(data => {
|
|
const config1Data = data[0];
|
|
const config2Data = data[1];
|
|
|
|
if (config1Data.write_data && config2Data.write_data) {
|
|
renderGraph('Lines per Second', config1Data.write_data, config2Data.write_data, 'lines', 10000);
|
|
renderGraph('Write Latency (ms)', config1Data.write_data, config2Data.write_data, 'latency', 10000, 'median');
|
|
}
|
|
if (config1Data.query_data && config2Data.query_data) {
|
|
renderGraph('Queries per Second', config1Data.query_data, config2Data.query_data, 'lines', 10000);
|
|
renderGraph('Query Latency (ms)', config1Data.query_data, config2Data.query_data, 'latency', 10000, 'median');
|
|
}
|
|
if (config1Data.system_data && config2Data.system_data) {
|
|
renderGraph('CPU Usage (%)', config1Data.system_data, config2Data.system_data, 'cpu_usage');
|
|
renderGraph('Memory Usage (MB)', config1Data.system_data, config2Data.system_data, 'memory_bytes');
|
|
}
|
|
});
|
|
});
|
|
|
|
// Render a graph using Chart.js
|
|
function renderGraph(title, config1Data, config2Data, yAxisKey, interval = 10000, aggregateFunction = 'sum') {
|
|
const container = document.getElementById('graph-container');
|
|
const canvas = document.createElement("canvas");
|
|
container.appendChild(canvas);
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
const labels = getXLabels(config1Data, interval);
|
|
const config1Values = getYValues(config1Data, yAxisKey, interval, aggregateFunction);
|
|
const config2Values = getYValues(config2Data, yAxisKey, interval, aggregateFunction);
|
|
|
|
new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: labels,
|
|
datasets: [
|
|
{
|
|
label: configName1Select.value,
|
|
data: config1Values,
|
|
borderColor: 'blue',
|
|
fill: false
|
|
},
|
|
{
|
|
label: configName2Select.value,
|
|
data: config2Values,
|
|
borderColor: 'orange',
|
|
fill: false
|
|
}
|
|
]
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
plugins: {
|
|
title: {
|
|
display: true,
|
|
text: title,
|
|
font: {
|
|
size: 30
|
|
}
|
|
},
|
|
legend: {
|
|
labels: {
|
|
font: {
|
|
size: 26
|
|
}
|
|
}
|
|
}
|
|
},
|
|
scales: {
|
|
x: {
|
|
title: {
|
|
display: true,
|
|
text: 'Time (seconds)',
|
|
font: {
|
|
size: 28
|
|
}
|
|
},
|
|
ticks: {
|
|
font: {
|
|
size: 26
|
|
}
|
|
}
|
|
},
|
|
y: {
|
|
title: {
|
|
display: true,
|
|
text: title,
|
|
font: {
|
|
size: 28
|
|
}
|
|
},
|
|
ticks: {
|
|
font: {
|
|
size: 26
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Get the x-axis labels based on the interval
|
|
function getXLabels(data, interval) {
|
|
const labels = [];
|
|
const numIntervals = Math.ceil(data[data.length - 1].test_time / interval);
|
|
for (let i = 0; i < numIntervals; i++) {
|
|
labels.push(i * interval / 1000);
|
|
}
|
|
return labels;
|
|
}
|
|
|
|
// Get the y-axis values based on the interval and y-axis key
|
|
function getYValues(data, yAxisKey, interval, aggregateFunction) {
|
|
const values = [];
|
|
const numIntervals = Math.ceil(data[data.length - 1].test_time / interval);
|
|
for (let i = 0; i < numIntervals; i++) {
|
|
const startTime = i * interval;
|
|
const endTime = (i + 1) * interval;
|
|
const intervalData = data.filter(d => d.test_time >= startTime && d.test_time < endTime);
|
|
let yValue;
|
|
if (aggregateFunction === 'sum') {
|
|
yValue = intervalData.reduce((sum, d) => sum + d[yAxisKey], 0) / (interval / 1000);
|
|
} else if (aggregateFunction === 'median') {
|
|
const sortedData = intervalData.map(d => d[yAxisKey]).sort((a, b) => a - b);
|
|
const middleIndex = Math.floor(sortedData.length / 2);
|
|
yValue = sortedData.length % 2 === 0 ? (sortedData[middleIndex - 1] + sortedData[middleIndex]) / 2 : sortedData[middleIndex];
|
|
}
|
|
values.push(yValue || null);
|
|
}
|
|
return values;
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|