blob: 2b887e542c310d0422f933ae49f22800377ebec1 [file] [log] [blame]
// This script deals with Boost ASIO handlers
// Will need to add code to visualize one-shot events
// Fields: HandlerNumber, Level,
// Creation time, Enter time, Exit time, EnterDescription,
// [ [Operation, time] ]
// Will use g_StartingSec as the starting of epoch
var ASIO_Data = [];
var ASIO_Timestamp = [];
function FindFirstEntrySlot(slots) {
let i = 0;
for (; i < slots.length; i++) {
if (slots[i] == undefined) break;
}
if (i >= slots.length) slots.push(undefined);
return i;
}
function SimplifyDesc(desc) {
const idx0 = desc.indexOf('0x');
if (idx0 == -1)
return desc;
else {
const d1 = desc.substr(idx0 + 2);
let idx1 = 0;
while (idx1 + 1 < d1.length &&
((d1[idx1] >= '0' && d1[idx1] <= '9') ||
(d1[idx1] >= 'A' && d1[idx1] <= 'F') ||
(d1[idx1] >= 'a' && d1[idx1] <= 'f'))) {
idx1++;
}
return desc.substr(0, idx0) + d1.substr(idx1)
}
}
function ParseBoostHandlerTimeline(content) {
let parsed_entries = [];
const lines = content.split('\n');
let slots = []; // In-flight handlers
let in_flight_id2level = {}; // In-flight ID to level
for (let lidx = 0; lidx < lines.length; lidx++) {
const line = lines[lidx];
if (line.startsWith('@asio|') == false) continue;
const sp = line.split('|');
const tag = sp[0], ts = sp[1], action = sp[2], desc = sp[3];
let handler_id = -999;
let ts_sec = parseFloat(ts);
const simp_desc = SimplifyDesc(desc);
if (action.indexOf('*') != -1) {
const idx = action.indexOf('*');
const handler_id = parseInt(action.substr(idx + 1));
const level = FindFirstEntrySlot(slots);
// Create an entry here
let entry = [
handler_id, level, ts_sec, undefined, undefined, desc, simp_desc, []
];
slots[level] = entry;
in_flight_id2level[handler_id] = level;
} else if (action[0] == '>') { // The program enters handler number X
handler_id = parseInt(action.substr(1));
if (handler_id in in_flight_id2level) {
const level = in_flight_id2level[handler_id];
let entry = slots[level];
entry[3] = ts_sec;
}
} else if (action[0] == '<') {
handler_id = parseInt(action.substr(1));
if (handler_id in in_flight_id2level) {
const level = in_flight_id2level[handler_id];
let entry = slots[level];
entry[4] = ts_sec;
slots[level] = undefined;
parsed_entries.push(entry);
delete in_flight_id2level[handler_id];
}
} else if (action[0] == '.') { // syscalls
}
}
console.log(
'Boost handler log: ' + parsed_entries.length + ' entries' +
', ' + slots.length + ' levels');
ASIO_Data = parsed_entries;
return parsed_entries;
}
function Group_ASIO(preprocessed, group_by) {
let grouped = {};
const IDXES = {'Layout Level': 1, 'Description': 5, 'Description1': 6};
for (var n = 0; n < preprocessed.length; n++) {
var key = ''
for (var i = 0; i < group_by.length; i++) {
if (i > 0) key += ' ';
key += ('' + preprocessed[n][IDXES[group_by[i]]]);
}
if (grouped[key] == undefined) grouped[key] = [];
grouped[key].push(preprocessed[n]);
}
return grouped;
}
function OnGroupByConditionChanged_ASIO() {
var tags = ['bah1', 'bah2', 'bah3'];
const v = boost_asio_handler_timeline_view;
v.GroupBy = [];
v.GroupByStr = '';
for (let i = 0; i < tags.length; i++) {
let cb = document.getElementById(tags[i]);
if (cb.checked) {
v.GroupBy.push(cb.value);
if (v.GroupByStr.length > 0) {
v.GroupByStr += ', ';
}
v.GroupByStr += cb.value;
}
}
let preproc = ASIO_Data;
let grouped = Group_ASIO(preproc, v.GroupBy);
GenerateTimeLine_ASIO(grouped);
boost_asio_handler_timeline_view.IsCanvasDirty = true;
}
function GenerateTimeLine_ASIO(grouped) {
const keys = Object.keys(grouped);
let sortedKeys = keys.slice();
let intervals = [];
let titles = [];
const was_starting_time_undefined = (g_StartingSec == undefined);
for (let i = 0; i < sortedKeys.length; i++) {
titles.push({"header":false, "title":sortedKeys[i], "intervals_idxes":[i] });
line = [];
for (let j = 0; j < grouped[sortedKeys[i]].length; j++) {
let entry = grouped[sortedKeys[i]][j];
let t0 = parseFloat(entry[3]);
let t1 = parseFloat(entry[4]);
if (was_starting_time_undefined) {
if (g_StartingSec == undefined) {
g_StartingSec = t0;
}
g_StartingSec = Math.min(g_StartingSec, t0);
}
line.push([t0, t1, entry, 'ok', 0]);
}
intervals.push(line);
}
// Time shift
for (let i = 0; i < intervals.length; i++) {
for (let j = 0; j < intervals[i].length; j++) {
let x = intervals[i][j];
x[0] -= g_StartingSec;
x[1] -= g_StartingSec;
}
}
boost_asio_handler_timeline_view.Intervals = intervals.slice();
boost_asio_handler_timeline_view.Titles = titles.slice();
boost_asio_handler_timeline_view.LayoutForOverlappingIntervals();
}
// Main view object for Boost handler timeline
boost_asio_handler_timeline_view = new BoostASIOHandlerTimelineView();
boost_asio_handler_timeline_view.IsCanvasDirty = true;
function draw_timeline_boost_asio_handler(ctx) {
boost_asio_handler_timeline_view.Render(ctx);
}
let Canvas_Asio = document.getElementById('my_canvas_boost_asio_handler');
Canvas_Asio.onmousemove = function(event) {
const v = boost_asio_handler_timeline_view;
v.MouseState.x = event.pageX - this.offsetLeft;
v.MouseState.y = event.pageY - this.offsetTop;
if (v.MouseState.pressed == true &&
v.MouseState.hoveredSide == 'timeline') { // Update highlighted area
v.HighlightedRegion.t1 = v.MouseXToTimestamp(v.MouseState.x);
}
v.OnMouseMove();
v.IsCanvasDirty = true;
v.linked_views.forEach(function(u) {
u.MouseState.x = event.pageX - Canvas_Asio.offsetLeft;
u.MouseState.y = 0; // Do not highlight any entry
if (u.MouseState.pressed == true &&
u.MouseState.hoveredSide == 'timeline') { // Update highlighted area
u.HighlightedRegion.t1 = u.MouseXToTimestamp(u.MouseState.x);
}
u.OnMouseMove();
u.IsCanvasDirty = true;
});
};
Canvas_Asio.onmousedown = function(event) {
if (event.button == 0) {
boost_asio_handler_timeline_view.OnMouseDown();
}
};
Canvas_Asio.onmouseup = function(event) {
if (event.button == 0) {
boost_asio_handler_timeline_view.OnMouseUp();
}
};
Canvas_Asio.onwheel = function(event) {
boost_asio_handler_timeline_view.OnMouseWheel(event);
}