Skip to content

Commit

Permalink
Add support for selecting CPU(s)
Browse files Browse the repository at this point in the history
This will allow the user to select the CPU(s) for all the graphs in CPU
Utilization, Perf Stat and Interrupt tabs.
  • Loading branch information
janaknat committed Jul 12, 2024
1 parent ce8b568 commit 477d726
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 15 deletions.
Binary file added src/html_files/configure.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
139 changes: 139 additions & 0 deletions src/html_files/configure.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
class RunConfig {
run: string;
cpu_count: number;
all_selected: boolean;
cpu_list: Array<string>;
}
class CPUList {
all_selected: boolean;
cpulist: Array<string>;
}
var run_config: Map<string, RunConfig> = new Map<string, RunConfig>();
var init_done = false;

function getCPUList(run) {
let ret = new CPUList();
ret.all_selected = run_config.get(run).all_selected;
ret.cpulist = run_config.get(run).cpu_list.slice();
return ret;
}

function formGlobalConfig() {
for (let i = 0; i < cpu_utilization_raw_data['runs'].length; i++) {
let this_run_data = cpu_utilization_raw_data['runs'][i];
let run_name = this_run_data['name'];
var config = new RunConfig();

/* Elemet 0 is aggregate. Don't use that. */
let key = this_run_data['keys'][1];
config.cpu_count = JSON.parse(this_run_data['key_values'][key]).length;
config.cpu_list = new Array<string>();
for (let i = 0; i < config.cpu_count; i++) {
config.cpu_list.push(i.toString());
}
config.all_selected = true;
run_config.set(run_name, config);
}
}

function isCPUListUnchanged(check_cpu_list, run) {
return check_cpu_list.sort().toString() === run_config.get(run).cpu_list.sort().toString();
}

function allSelect(elem: HTMLInputElement, run) {
let checkboxes = document.getElementsByName(`${run}-cpulist`);
for (let i = 0; i < checkboxes.length; i++) {
(checkboxes[i] as HTMLInputElement).checked = elem.checked;
toggleCheckbox(checkboxes[i] as HTMLInputElement, run, false);
}
}

function allCPUsCheck(run) {
let checkboxes = document.getElementsByName(`${run}-cpulist`);
let allToggled = true;
for (let i = 0; i < checkboxes.length; i++) {
if (!((checkboxes[i] as HTMLInputElement).checked)) {
allToggled = false;
break;
}
}
(document.getElementById(`${run}-CPUAll`) as HTMLInputElement).checked = allToggled;
run_config.get(run).all_selected = allToggled;
}

function toggleCheckbox(elem: HTMLInputElement, run, check) {
let cpu_list = run_config.get(run).cpu_list;
if (elem.checked) {
if (cpu_list.indexOf(elem.value) == -1) {
cpu_list.push(elem.value);
}
} else {
let index = cpu_list.indexOf(elem.value);
if (index != -1) {
cpu_list.splice(index, 1);
}
}
if (check) {
allCPUsCheck(run);
}
}

function createCheckbox(run, id, label_str, name, value, toggle_func) {
let elem = document.createElement("input");
elem.setAttribute("type", "checkbox");
elem.id = id;
elem.name = name;
elem.value = value;
elem.addEventListener("click", function (ev: Event) {
toggle_func(this, run, true);
}, false);
let label = document.createElement("label");
label.htmlFor = id;
label.innerHTML = label_str;

let cpu_div = document.createElement("div");
cpu_div.appendChild(elem);
cpu_div.appendChild(label);
return cpu_div;
}

function createCPUConfigure(container_id, run) {
let config = run_config.get(run);

/* Add a Toggle All checkbox */
let all_cpu = createCheckbox(run, `${run}-CPUAll`, 'Toggle All', '', -1, allSelect);
addElemToNode(container_id, all_cpu);

let cpu_configure_list = document.createElement("div");
cpu_configure_list.id = `${run}-cpus-configure-list`;
cpu_configure_list.style.display = "grid";
addElemToNode(container_id, cpu_configure_list);
let max_cpus = config.cpu_count;
let max_columns = max_cpus / 16;
let cpus_per_column = Math.floor(max_cpus / max_columns);
for (let column = 0; column < max_columns; column++) {
let cpus_start = column * cpus_per_column;
let cpus_end = cpus_start + cpus_per_column;
if (cpus_end > max_cpus) {
cpus_end = max_cpus;
}
for (let i = cpus_start, row = 1; i < cpus_end; i++, row++) {
let cpu_div = createCheckbox(run, `${run}-CPU${i}`, `CPU ${i}`, `${run}-cpulist`, i, toggleCheckbox);
cpu_div.style.gridColumn = `${column + 1}`;
cpu_div.style.gridRow = `${row}`;
addElemToNode(`${run}-cpus-configure-list`, cpu_div);
}
}
document.getElementById(`${run}-CPUAll`).click();
}

function configure() {
if (init_done) {
return;
}
clear_and_create('configure');
runs_raw.forEach(function (value, index, arr) {
createCPUConfigure(`${value}-configure-per-data`, value);
});
init_done = true;
}
13 changes: 9 additions & 4 deletions src/html_files/cpu_utilization.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
let got_cpu_util_data = false;
let util_cpu_list: Map<string, CPUList> = new Map<string, CPUList>();

function getUtilizationType(run, elem, type, run_data) {
var cpu_type_datas = [];
Expand All @@ -9,18 +10,21 @@ function getUtilizationType(run, elem, type, run_data) {
data.forEach(function (value, index, arr) {
var x_time = [];
var y_data = [];
cpu = value.cpu;
cpu = value.cpu.toString();
type_data = value.data;
type_data.forEach(function (i_value, i_index, i_arr) {
x_time.push(i_value.time.TimeDiff);
y_data.push(i_value.value);
});
var cpu_type_data = {
var cpu_type_data: Partial<Plotly.PlotData> = {
name: `CPU ${cpu}`,
x: x_time,
y: y_data,
type: 'scatter',
};
}
if (util_cpu_list.get(run).cpulist.indexOf(cpu) == -1) {
cpu_type_data.visible = 'legendonly';
}
cpu_type_datas.push(cpu_type_data);
});
var TESTER = elem;
Expand Down Expand Up @@ -134,12 +138,13 @@ function getCpuUtilization(elem, run, run_data) {
Plotly.newPlot(TESTER, data_list, layout, { frameMargins: 0 });
}
function cpuUtilization() {
if (got_cpu_util_data) {
if (got_cpu_util_data && allRunCPUListUnchanged(util_cpu_list)) {
return;
}
clear_and_create('cpuutilization');
for (let i = 0; i < cpu_utilization_raw_data['runs'].length; i++) {
let run_name = cpu_utilization_raw_data['runs'][i]['name'];
util_cpu_list.set(run_name, getCPUList(run_name));
let elem_id = `${run_name}-cpuutilization-per-data`;
let this_run_data = cpu_utilization_raw_data['runs'][i];
getCpuUtilization(document.getElementById(elem_id), run_name, this_run_data['key_values']['aggregate']);
Expand Down
16 changes: 15 additions & 1 deletion src/html_files/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ body {

/* Style the buttons inside the tab */
.tab button {
display: block;
display: grid;
background-color: inherit;
color: black;
padding: 22px 16px;
Expand All @@ -51,6 +51,20 @@ body {
font-size: 17px;
}

.icon-text {
grid-column: 1;
}

.configure {
grid-column: 2;
background-image: url("images/configure.png");
height: 100%;
width: 100%;
background-repeat: no-repeat;
background-position-x: center;
background-position-y: center;
}

.all-runs {
grid-row: 1;
position: sticky;
Expand Down
10 changes: 9 additions & 1 deletion src/html_files/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
<html>
<head>
<link rel="stylesheet" href="index.css">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="icon" type="image/x-icon" href="images/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>APerf</title>
</head>
<body>
<div class="tab">
<div class="aperf">APerf</div>
<button class="tablinks" name="configure"><div class="icon-text">Configure</div><div class="configure"/></button>
<!--- Configure should be the first tab. Add any new tabs below this. -->
<button class="tablinks" name="system_info" id="default">SUT Config</button>
<button class="tablinks" name="cpu_utilization">CPU Utilization</button>
<button class="tablinks" name="flamegraphs">Flamegraphs</button>
Expand Down Expand Up @@ -98,6 +100,11 @@ <h3>Hide N/A and all-zero graphs:</h3>
<div id="aperfstat" class="tabcontent">
<div id="aperfstat-runs"></div>
</div>
<div id="configure" class="tabcontent">
<div id="configure-runs" class="extra">
<div id="cpus-configure"></div>
</div>
</div>
</div>
<script type="text/javascript" src="data/js/runs.js"></script>
<script type="text/javascript" src="data/js/system_info.js"></script>
Expand Down Expand Up @@ -130,6 +137,7 @@ <h3>Hide N/A and all-zero graphs:</h3>
<script type="text/javascript" src="js/perf_stat.js"></script>
<script type="text/javascript" src="js/netstat.js"></script>
<script type="text/javascript" src="js/aperf_run_stats.js"></script>
<script type="text/javascript" src="js/configure.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
3 changes: 3 additions & 0 deletions src/html_files/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ DataTypes.set('top_functions', {name: 'topfunctions', hideClass: '', trueId: '',
DataTypes.set('processes', {name: 'processes', hideClass: '', trueId: '', callback: processes});
DataTypes.set('perfstat', {name: 'perfstat', hideClass: '', trueId: '', callback: perfStat});
DataTypes.set('aperfstat', {name: 'aperfstat', hideClass: '', trueId: '', callback: aperfStat});
DataTypes.set('configure', {name: 'configure', hideClass: '', trueId: '', callback: configure});

function openData(evt: Event, elem: HTMLButtonElement) {
var tabName: string = elem.name;
Expand Down Expand Up @@ -118,5 +119,7 @@ function create_runs_header() {
// Set Runs header
create_runs_header();

formGlobalConfig();

// Show landing page
document.getElementById("default").click();
9 changes: 7 additions & 2 deletions src/html_files/interrupts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
let got_interrupt_data = false;
let interrupt_cpu_list: Map<string, CPUList> = new Map<string, CPUList>();

function getLine(run, elem, key, run_data) {
var data = JSON.parse(run_data);
Expand All @@ -15,12 +16,15 @@ function getLine(run, elem, key, run_data) {
}
})
})
var interrupt_cpu_data = {
var interrupt_cpu_data: Partial<Plotly.PlotData> = {
name: `CPU ${cpu}`,
x: x_time,
y: y_data,
type: 'scatter',
};
if (interrupt_cpu_list.get(run).cpulist.indexOf(cpu.toString()) == -1) {
interrupt_cpu_data.visible = 'legendonly';
}
interrupt_type_datas.push(interrupt_cpu_data);
}
var title;
Expand Down Expand Up @@ -56,12 +60,13 @@ function getLines(run, container_id, keys, run_data) {
}

function interrupts() {
if (got_interrupt_data) {
if (got_interrupt_data && allRunCPUListUnchanged(interrupt_cpu_list)) {
return;
}
clear_and_create('interrupts');
for (let i = 0; i < interrupts_raw_data['runs'].length; i++) {
let run_name = interrupts_raw_data['runs'][i]['name'];
interrupt_cpu_list.set(run_name, getCPUList(run_name));
let elem_id = `${run_name}-interrupts-per-data`;
let this_run_data = interrupts_raw_data['runs'][i];
getLines(run_name, elem_id, this_run_data['keys'], this_run_data['key_values']);
Expand Down
22 changes: 18 additions & 4 deletions src/html_files/perf_stat.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
let got_perf_stat_data = false;

let perf_cpu_list: Map<string, CPUList> = new Map<string, CPUList>();

function getEvents(run, container_id, keys, run_data) {
if (keys.length == 0) {
var no_data_div = document.createElement('div');
Expand All @@ -13,7 +15,7 @@ function getEvents(run, container_id, keys, run_data) {
elem.id = `perfstat-${run}-${value}`;
elem.style.float = "none";
addElemToNode(container_id, elem);
emptyOrCallback(keys, false, getEvent, elem, value, run_data);
emptyOrCallback(keys, false, getEvent, elem, value, run_data, run);
}
}
}
Expand All @@ -32,7 +34,7 @@ function addData(perfstat_data, stat, timediff) {
}
})
}
function getEvent(elem, key, run_data) {
function getEvent(elem, key, run_data, run) {
var data = JSON.parse(run_data);
var perfstat_datas = [];
data.data[0].cpus.forEach(function (value, index, arr) {
Expand All @@ -51,6 +53,7 @@ function getEvent(elem, key, run_data) {
var end_datas = [];
perfstat_datas.forEach(function (value, index, arr) {
var cpu_string = "";
let cpu = value.cpu.toString();
if (value.cpu > -1) {
cpu_string = `CPU ${value.cpu}`;
}
Expand All @@ -63,7 +66,17 @@ function getEvent(elem, key, run_data) {
y: value.y_data,
type: 'scatter',
};
end_datas.push(perfstat_line);
if (cpu_string == 'Aggregate') {
if (!perf_cpu_list.get(run).all_selected) {
perfstat_line.visible = 'legendonly';
}
end_datas.unshift(perfstat_line);
} else {
if (perf_cpu_list.get(run).cpulist.indexOf(cpu) == -1) {
perfstat_line.visible = 'legendonly';
}
end_datas.push(perfstat_line);
}
})
let limits = key_limits.get(key);
var layout = {
Expand All @@ -80,13 +93,14 @@ function getEvent(elem, key, run_data) {
}

function perfStat() {
if (got_perf_stat_data) {
if (got_perf_stat_data && allRunCPUListUnchanged(perf_cpu_list)) {
return;
}
clear_and_create('perfstat');
form_graph_limits(perf_stat_raw_data);
for (let i = 0; i < perf_stat_raw_data['runs'].length; i++) {
let run_name = perf_stat_raw_data['runs'][i]['name'];
perf_cpu_list.set(run_name, getCPUList(run_name));
let elem_id = `${run_name}-perfstat-per-data`;
let this_run_data = perf_stat_raw_data['runs'][i];
getEvents(run_name, elem_id, this_run_data['keys'], this_run_data['key_values']);
Expand Down
Loading

0 comments on commit 477d726

Please sign in to comment.