Add experiment_results_visualization/js/ui.js
This commit is contained in:
parent
0e33154c45
commit
0a3b8c027a
1 changed files with 161 additions and 0 deletions
161
experiment_results_visualization/js/ui.js
Normal file
161
experiment_results_visualization/js/ui.js
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
/**
|
||||||
|
* UI Update Module for Experiment Results Visualization
|
||||||
|
* Handles summary cards, charts, and table rendering.
|
||||||
|
* @module ui
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders statistical summary cards.
|
||||||
|
* @param {Object} experiment_data - Contains pinned and unpinned experiment results.
|
||||||
|
*/
|
||||||
|
export function renderSummary(experiment_data) {
|
||||||
|
const container = document.querySelector('.summary-section');
|
||||||
|
if (!container) return;
|
||||||
|
container.innerHTML = '';
|
||||||
|
|
||||||
|
const createCard = (title, value) => {
|
||||||
|
const card = document.createElement('div');
|
||||||
|
card.className = 'summary-card';
|
||||||
|
const heading = document.createElement('h3');
|
||||||
|
heading.textContent = title;
|
||||||
|
const valElem = document.createElement('p');
|
||||||
|
valElem.textContent = value;
|
||||||
|
card.appendChild(heading);
|
||||||
|
card.appendChild(valElem);
|
||||||
|
return card;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pinned = experiment_data?.pinned ?? [];
|
||||||
|
const unpinned = experiment_data?.unpinned ?? [];
|
||||||
|
|
||||||
|
const pinnedLatencies = pinned.map(r => r.latency_ms ?? 0);
|
||||||
|
const unpinnedLatencies = unpinned.map(r => r.latency_ms ?? 0);
|
||||||
|
const percentiles = (arr, p) => {
|
||||||
|
if (!arr.length) return 0;
|
||||||
|
const sorted = [...arr].sort((a, b) => a - b);
|
||||||
|
const idx = Math.floor((p / 100) * sorted.length);
|
||||||
|
return sorted[idx] ?? 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
const pinnedP95 = percentiles(pinnedLatencies, 95).toFixed(2);
|
||||||
|
const pinnedP99 = percentiles(pinnedLatencies, 99).toFixed(2);
|
||||||
|
const unpinnedP95 = percentiles(unpinnedLatencies, 95).toFixed(2);
|
||||||
|
const unpinnedP99 = percentiles(unpinnedLatencies, 99).toFixed(2);
|
||||||
|
|
||||||
|
const correlation = (() => {
|
||||||
|
if (pinnedLatencies.length !== unpinnedLatencies.length || !pinnedLatencies.length) return 0;
|
||||||
|
const avgPinned = pinnedLatencies.reduce((a,b)=>a+b,0)/pinnedLatencies.length;
|
||||||
|
const avgUnpinned = unpinnedLatencies.reduce((a,b)=>a+b,0)/unpinnedLatencies.length;
|
||||||
|
let num=0,den1=0,den2=0;
|
||||||
|
for(let i=0;i<pinnedLatencies.length;i++){
|
||||||
|
const x = pinnedLatencies[i] - avgPinned;
|
||||||
|
const y = unpinnedLatencies[i] - avgUnpinned;
|
||||||
|
num += x*y;
|
||||||
|
den1 += x*x;
|
||||||
|
den2 += y*y;
|
||||||
|
}
|
||||||
|
return (num / Math.sqrt(den1 * den2)).toFixed(3);
|
||||||
|
})();
|
||||||
|
|
||||||
|
container.appendChild(createCard('Pinned p95', `${pinnedP95} ms`));
|
||||||
|
container.appendChild(createCard('Pinned p99', `${pinnedP99} ms`));
|
||||||
|
container.appendChild(createCard('Unpinned p95', `${unpinnedP95} ms`));
|
||||||
|
container.appendChild(createCard('Unpinned p99', `${unpinnedP99} ms`));
|
||||||
|
container.appendChild(createCard('Correlation (latency)', correlation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders comparative charts for pinned vs unpinned runs.
|
||||||
|
* Expects charting library available in global scope (e.g., Chart.js or similar).
|
||||||
|
* @param {Object} experiment_data - Experiment dataset
|
||||||
|
*/
|
||||||
|
export function renderCharts(experiment_data) {
|
||||||
|
const pinned = experiment_data?.pinned ?? [];
|
||||||
|
const unpinned = experiment_data?.unpinned ?? [];
|
||||||
|
const pinnedCanvas = document.getElementById('chart-pinned');
|
||||||
|
const unpinnedCanvas = document.getElementById('chart-unpinned');
|
||||||
|
if (!pinnedCanvas || !unpinnedCanvas) return;
|
||||||
|
|
||||||
|
const pinnedData = pinned.map(r => r.latency_ms ?? 0);
|
||||||
|
const unpinnedData = unpinned.map(r => r.latency_ms ?? 0);
|
||||||
|
const labels = pinned.map((_, i) => `Run ${i+1}`);
|
||||||
|
|
||||||
|
const createChart = (ctx, label, data, color) => {
|
||||||
|
if (!window.Chart) return;
|
||||||
|
if (ctx.__chartInstance) ctx.__chartInstance.destroy();
|
||||||
|
ctx.__chartInstance = new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels,
|
||||||
|
datasets: [{
|
||||||
|
label,
|
||||||
|
data,
|
||||||
|
borderColor: color,
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
borderWidth: 2
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
y: { beginAtZero: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
createChart(pinnedCanvas.getContext('2d'), 'Pinned Latency (ms)', pinnedData, '#4caf50');
|
||||||
|
createChart(unpinnedCanvas.getContext('2d'), 'Unpinned Latency (ms)', unpinnedData, '#f44336');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a table view of runs data.
|
||||||
|
* @param {Object} experiment_data - Dataset from API including pinned and unpinned.
|
||||||
|
*/
|
||||||
|
export function renderTable(experiment_data) {
|
||||||
|
const container = document.querySelector('.runs-table');
|
||||||
|
if (!container) return;
|
||||||
|
|
||||||
|
const pinned = experiment_data?.pinned ?? [];
|
||||||
|
const unpinned = experiment_data?.unpinned ?? [];
|
||||||
|
|
||||||
|
const table = document.createElement('table');
|
||||||
|
table.className = 'runs-table__inner';
|
||||||
|
|
||||||
|
const thead = document.createElement('thead');
|
||||||
|
thead.innerHTML = `
|
||||||
|
<tr>
|
||||||
|
<th>Run ID</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Latency (ms)</th>
|
||||||
|
<th>Timestamp</th>
|
||||||
|
</tr>
|
||||||
|
`;
|
||||||
|
table.appendChild(thead);
|
||||||
|
|
||||||
|
const tbody = document.createElement('tbody');
|
||||||
|
|
||||||
|
const makeRow = (run, type) => {
|
||||||
|
const tr = document.createElement('tr');
|
||||||
|
const tdId = document.createElement('td');
|
||||||
|
const tdType = document.createElement('td');
|
||||||
|
const tdLatency = document.createElement('td');
|
||||||
|
const tdTime = document.createElement('td');
|
||||||
|
|
||||||
|
tdId.textContent = run.id ?? '-';
|
||||||
|
tdType.textContent = type;
|
||||||
|
tdLatency.textContent = run.latency_ms?.toFixed(2) ?? '-';
|
||||||
|
tdTime.textContent = new Date(run.timestamp ?? Date.now()).toLocaleString();
|
||||||
|
|
||||||
|
tr.append(tdId, tdType, tdLatency, tdTime);
|
||||||
|
return tr;
|
||||||
|
};
|
||||||
|
|
||||||
|
pinned.forEach(run => tbody.appendChild(makeRow(run, 'pinned')));
|
||||||
|
unpinned.forEach(run => tbody.appendChild(makeRow(run, 'unpinned')));
|
||||||
|
|
||||||
|
table.appendChild(tbody);
|
||||||
|
container.innerHTML = '';
|
||||||
|
container.appendChild(table);
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue