Skip to content

Commit

Permalink
cpu util plot
Browse files Browse the repository at this point in the history
  • Loading branch information
LeandroTreu committed Apr 22, 2024
1 parent dfb55cf commit cff66a9
Show file tree
Hide file tree
Showing 6 changed files with 186 additions and 14 deletions.
6 changes: 3 additions & 3 deletions profile_parser/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
// Take tasks as framtimes if they are at least this long in microseconds.
// Very short tasks (< 2ms) don't correspond to frames drawn.
const MIN_TASK_DURATION = 2000;
const MIN_FRAME_DURATION = 2000;
const files_in_directory = fs_1.default.readdirSync("traces");
for (let i = 0; i < files_in_directory.length; ++i) {
const filename = files_in_directory[i];
Expand Down Expand Up @@ -41,8 +41,8 @@ for (let i = 0; i < files_in_directory.length; ++i) {
let event = traceEvents[i];
if (event.pid === main_renderer_pid && event.tid === main_renderer_tid
&& event.name === "RunTask" && event.ph === "X") {
if (event.dur > MIN_TASK_DURATION) {
frametimeEvents.tasks.push(event);
frametimeEvents.tasks.push(event);
if (event.dur > MIN_FRAME_DURATION) {
frametimes.push(event.dur / 1000);
}
}
Expand Down
7 changes: 4 additions & 3 deletions profile_parser/parse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import fs from 'fs';

// Take tasks as framtimes if they are at least this long in microseconds.
// Very short tasks (< 2ms) don't correspond to frames drawn.
const MIN_TASK_DURATION = 2000;
const MIN_FRAME_DURATION = 2000;

const files_in_directory = fs.readdirSync("traces");

Expand Down Expand Up @@ -53,8 +53,9 @@ for (let i = 0; i < files_in_directory.length; ++i) {
if (event.pid === main_renderer_pid && event.tid === main_renderer_tid
&& event.name === "RunTask" && event.ph === "X") {

if (event.dur > MIN_TASK_DURATION) {
frametimeEvents.tasks.push(event);
frametimeEvents.tasks.push(event);

if (event.dur > MIN_FRAME_DURATION) {
frametimes.push(event.dur / 1000);
}
}
Expand Down
73 changes: 73 additions & 0 deletions profile_parser/plot_cpu_util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const nodeplotlib_1 = require("nodeplotlib");
const PLOT_FILES_IN_ONE_GRAPH = true;
const CPU_UTIL_SAMPLE_WINDOW_SIZE_MS = 500; // Adjust for sampling resolution / smoothing
const files_in_directory = fs_1.default.readdirSync("results");
let data = [];
const layout = {
title: "CPU Utilization",
xaxis: { title: "Time (s)" },
yaxis: { title: "Utilization (%)", range: [0, 100] },
};
for (let i = 0; i < files_in_directory.length; ++i) {
const filename = files_in_directory[i];
const filenamejsonsuffix = filename.substring(filename.length - 5, filename.length);
if (filenamejsonsuffix === ".json") {
const file_path = "results/" + filename;
console.log("Parsing file %s ...", filename);
const file_data = fs_1.default.readFileSync(file_path, { encoding: 'utf8' });
const json_data = JSON.parse(file_data);
const tasks = json_data.tasks;
// Sort tasks by timestamps
tasks.sort((a, b) => a.ts - b.ts);
// All units in microseconds
let cpu_util_samples = [];
let x_axis = [];
const total_duration = tasks[tasks.length - 1].ts + tasks[tasks.length - 1].dur - tasks[0].ts;
const window_size = CPU_UTIL_SAMPLE_WINDOW_SIZE_MS * 1000;
let window_start = tasks[0].ts;
let window_end = window_start + window_size;
const n_samples = Math.floor(total_duration / window_size);
for (let i = 0; i < n_samples; ++i) {
let sample_cpu_idle_time = window_size;
for (let j = 0; j < tasks.length; ++j) {
const event = tasks[j];
if (event.ts <= window_end && event.ts + event.dur >= window_start) {
const clipped_task_time = Math.min(event.dur, window_end - event.ts, event.ts + event.dur - window_start);
sample_cpu_idle_time -= clipped_task_time;
}
}
if (sample_cpu_idle_time < 0) {
sample_cpu_idle_time = 0;
}
let sample_cpu_util = 1 - (sample_cpu_idle_time / window_size);
sample_cpu_util = Math.round(10000 * sample_cpu_util) / 10000;
cpu_util_samples.push(sample_cpu_util * 100);
x_axis.push((window_start - tasks[0].ts) / 1000000);
window_start = window_start + window_size;
window_end = window_start + window_size;
}
const line = {
x: x_axis,
y: cpu_util_samples,
type: 'scatter',
name: filename,
mode: 'lines',
line: {
width: 1
}
};
data.push(line);
if (!PLOT_FILES_IN_ONE_GRAPH) {
(0, nodeplotlib_1.plot)(data, layout);
}
}
}
if (PLOT_FILES_IN_ONE_GRAPH) {
(0, nodeplotlib_1.plot)(data, layout);
}
88 changes: 88 additions & 0 deletions profile_parser/plot_cpu_util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import fs from 'fs';
import { plot, Plot } from 'nodeplotlib';

const PLOT_FILES_IN_ONE_GRAPH = true;
const CPU_UTIL_SAMPLE_WINDOW_SIZE_MS = 500; // Adjust for sampling resolution / smoothing

const files_in_directory = fs.readdirSync("results");

let data: Plot[] = [];
const layout = {
title: "CPU Utilization",
xaxis: {title: "Time (s)"},
yaxis: {title: "Utilization (%)", range: [0, 100]},
}

for (let i = 0; i < files_in_directory.length; ++i) {
const filename = files_in_directory[i];
const filenamejsonsuffix = filename.substring(filename.length - 5, filename.length)

if (filenamejsonsuffix === ".json") {

const file_path = "results/" + filename;
console.log("Parsing file %s ...", filename);
const file_data = fs.readFileSync(file_path, { encoding: 'utf8' });

const json_data = JSON.parse(file_data);
const tasks = json_data.tasks as Array<any>;

// Sort tasks by timestamps
tasks.sort((a, b) => a.ts - b.ts);

// All units in microseconds
let cpu_util_samples = [];
let x_axis = [];
const total_duration = tasks[tasks.length-1].ts + tasks[tasks.length-1].dur - tasks[0].ts;
const window_size = CPU_UTIL_SAMPLE_WINDOW_SIZE_MS * 1000;
let window_start = tasks[0].ts;
let window_end = window_start + window_size;
const n_samples = Math.floor(total_duration / window_size);

for (let i = 0; i < n_samples; ++i) {

let sample_cpu_idle_time = window_size;
for (let j = 0; j < tasks.length; ++j) {

const event = tasks[j];
if (event.ts <= window_end && event.ts + event.dur >= window_start) {
const clipped_task_time = Math.min(event.dur, window_end - event.ts, event.ts + event.dur - window_start);
sample_cpu_idle_time -= clipped_task_time;
}
}
if (sample_cpu_idle_time < 0) {
sample_cpu_idle_time = 0;
}

let sample_cpu_util = 1 - (sample_cpu_idle_time / window_size);
sample_cpu_util = Math.round(10000 * sample_cpu_util) / 10000;
cpu_util_samples.push(sample_cpu_util * 100);
x_axis.push((window_start - tasks[0].ts) / 1000000);

window_start = window_start + window_size;
window_end = window_start + window_size;
}


const line: Plot = {
x: x_axis,
y: cpu_util_samples,
type: 'scatter',
name: filename,
mode: 'lines',
line: {
width: 1
}
};
data.push(line);
if (!PLOT_FILES_IN_ONE_GRAPH) {
plot(data, layout);
}

}

}

if (PLOT_FILES_IN_ONE_GRAPH) {
plot(data, layout);
}

13 changes: 9 additions & 4 deletions profile_parser/plot_frametime_histogram.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = __importDefault(require("fs"));
const nodeplotlib_1 = require("nodeplotlib");
// Take tasks as framtimes if they are at least this long in microseconds.
// Very short tasks (< 2ms) don't correspond to frames drawn.
const MIN_FRAME_DURATION = 2000;
const MAX_BIN_X_VALUE = 200;
const files_in_directory = fs_1.default.readdirSync("results");
for (let i = 0; i < files_in_directory.length; ++i) {
Expand All @@ -20,11 +23,13 @@ for (let i = 0; i < files_in_directory.length; ++i) {
let x_array = [];
for (let i = 0; i < frames.length; ++i) {
const event = frames[i];
let event_dur_ms = event.dur / 1000;
if (event_dur_ms > MAX_BIN_X_VALUE) {
event_dur_ms = MAX_BIN_X_VALUE;
if (event.dur > MIN_FRAME_DURATION) {
let event_dur_ms = event.dur / 1000;
if (event_dur_ms > MAX_BIN_X_VALUE) {
event_dur_ms = MAX_BIN_X_VALUE;
}
x_array.push(event_dur_ms);
}
x_array.push(event_dur_ms);
}
const hist = {
x: x_array,
Expand Down
13 changes: 9 additions & 4 deletions profile_parser/plot_frametime_histogram.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import fs from 'fs';
import { plot, Plot } from 'nodeplotlib';

// Take tasks as framtimes if they are at least this long in microseconds.
// Very short tasks (< 2ms) don't correspond to frames drawn.
const MIN_FRAME_DURATION = 2000;
const MAX_BIN_X_VALUE = 200;

const files_in_directory = fs.readdirSync("results");
Expand All @@ -21,11 +24,13 @@ for (let i = 0; i < files_in_directory.length; ++i) {
let x_array: number[] = [];
for (let i = 0; i < frames.length; ++i) {
const event = frames[i];
let event_dur_ms = event.dur / 1000;
if (event_dur_ms > MAX_BIN_X_VALUE) {
event_dur_ms = MAX_BIN_X_VALUE;
if (event.dur > MIN_FRAME_DURATION) {
let event_dur_ms = event.dur / 1000;
if (event_dur_ms > MAX_BIN_X_VALUE) {
event_dur_ms = MAX_BIN_X_VALUE;
}
x_array.push(event_dur_ms);
}
x_array.push(event_dur_ms);
}
const hist: Plot = {
x: x_array,
Expand Down

0 comments on commit cff66a9

Please sign in to comment.