1// This script deals with Boost ASIO handlers 2// Will need to add code to visualize one-shot events 3 4// Fields: HandlerNumber, Level, 5// Creation time, Enter time, Exit time, EnterDescription, 6// [ [Operation, time] ] 7 8// Will use g_StartingSec as the starting of epoch 9 10var ASIO_Data = []; 11var ASIO_Timestamp = []; 12 13function FindFirstEntrySlot(slots) { 14 let i = 0; 15 for (; i < slots.length; i++) { 16 if (slots[i] == undefined) break; 17 } 18 if (i >= slots.length) slots.push(undefined); 19 return i; 20} 21 22function SimplifyDesc(desc) { 23 const idx0 = desc.indexOf('0x'); 24 if (idx0 == -1) 25 return desc; 26 else { 27 const d1 = desc.substr(idx0 + 2); 28 let idx1 = 0; 29 while (idx1 + 1 < d1.length && 30 ((d1[idx1] >= '0' && d1[idx1] <= '9') || 31 (d1[idx1] >= 'A' && d1[idx1] <= 'F') || 32 (d1[idx1] >= 'a' && d1[idx1] <= 'f'))) { 33 idx1++; 34 } 35 return desc.substr(0, idx0) + d1.substr(idx1) 36 } 37} 38 39function ParseBoostHandlerTimeline(content) { 40 let parsed_entries = []; 41 const lines = content.split('\n'); 42 let slots = []; // In-flight handlers 43 let in_flight_id2level = {}; // In-flight ID to level 44 45 for (let lidx = 0; lidx < lines.length; lidx++) { 46 const line = lines[lidx]; 47 if (line.startsWith('@asio|') == false) continue; 48 const sp = line.split('|'); 49 50 const tag = sp[0], ts = sp[1], action = sp[2], desc = sp[3]; 51 let handler_id = -999; 52 let ts_sec = parseFloat(ts); 53 const simp_desc = SimplifyDesc(desc); 54 55 if (action.indexOf('*') != -1) { 56 const idx = action.indexOf('*'); 57 const handler_id = parseInt(action.substr(idx + 1)); 58 const level = FindFirstEntrySlot(slots); 59 60 // Create an entry here 61 let entry = [ 62 handler_id, level, ts_sec, undefined, undefined, desc, simp_desc, [] 63 ]; 64 65 slots[level] = entry; 66 in_flight_id2level[handler_id] = level; 67 } else if (action[0] == '>') { // The program enters handler number X 68 handler_id = parseInt(action.substr(1)); 69 if (handler_id in in_flight_id2level) { 70 const level = in_flight_id2level[handler_id]; 71 let entry = slots[level]; 72 entry[3] = ts_sec; 73 } 74 } else if (action[0] == '<') { 75 handler_id = parseInt(action.substr(1)); 76 if (handler_id in in_flight_id2level) { 77 const level = in_flight_id2level[handler_id]; 78 let entry = slots[level]; 79 entry[4] = ts_sec; 80 slots[level] = undefined; 81 parsed_entries.push(entry); 82 delete in_flight_id2level[handler_id]; 83 } 84 } else if (action[0] == '.') { // syscalls 85 } 86 } 87 88 console.log( 89 'Boost handler log: ' + parsed_entries.length + ' entries' + 90 ', ' + slots.length + ' levels'); 91 ASIO_Data = parsed_entries; 92 return parsed_entries; 93} 94 95function Group_ASIO(preprocessed, group_by) { 96 let grouped = {}; 97 const IDXES = {'Layout Level': 1, 'Description': 5, 'Description1': 6}; 98 for (var n = 0; n < preprocessed.length; n++) { 99 var key = '' 100 for (var i = 0; i < group_by.length; i++) { 101 if (i > 0) key += ' '; 102 key += ('' + preprocessed[n][IDXES[group_by[i]]]); 103 } 104 if (grouped[key] == undefined) grouped[key] = []; 105 grouped[key].push(preprocessed[n]); 106 } 107 return grouped; 108} 109 110function OnGroupByConditionChanged_ASIO() { 111 var tags = ['bah1', 'bah2', 'bah3']; 112 const v = boost_asio_handler_timeline_view; 113 v.GroupBy = []; 114 v.GroupByStr = ''; 115 for (let i = 0; i < tags.length; i++) { 116 let cb = document.getElementById(tags[i]); 117 if (cb.checked) { 118 v.GroupBy.push(cb.value); 119 if (v.GroupByStr.length > 0) { 120 v.GroupByStr += ', '; 121 } 122 v.GroupByStr += cb.value; 123 } 124 } 125 let preproc = ASIO_Data; 126 let grouped = Group_ASIO(preproc, v.GroupBy); 127 GenerateTimeLine_ASIO(grouped); 128 boost_asio_handler_timeline_view.IsCanvasDirty = true; 129} 130 131function GenerateTimeLine_ASIO(grouped) { 132 const keys = Object.keys(grouped); 133 let sortedKeys = keys.slice(); 134 let intervals = []; 135 let titles = []; 136 137 const was_starting_time_undefined = (g_StartingSec == undefined); 138 139 for (let i = 0; i < sortedKeys.length; i++) { 140 titles.push({"header":false, "title":sortedKeys[i], "intervals_idxes":[i] }); 141 line = []; 142 for (let j = 0; j < grouped[sortedKeys[i]].length; j++) { 143 let entry = grouped[sortedKeys[i]][j]; 144 let t0 = parseFloat(entry[3]); 145 let t1 = parseFloat(entry[4]); 146 147 if (was_starting_time_undefined) { 148 if (g_StartingSec == undefined) { 149 g_StartingSec = t0; 150 } 151 g_StartingSec = Math.min(g_StartingSec, t0); 152 } 153 154 line.push([t0, t1, entry, 'ok', 0]); 155 } 156 intervals.push(line); 157 } 158 159 // Time shift 160 for (let i = 0; i < intervals.length; i++) { 161 for (let j = 0; j < intervals[i].length; j++) { 162 let x = intervals[i][j]; 163 x[0] -= g_StartingSec; 164 x[1] -= g_StartingSec; 165 } 166 } 167 168 boost_asio_handler_timeline_view.Intervals = intervals.slice(); 169 boost_asio_handler_timeline_view.Titles = titles.slice(); 170 boost_asio_handler_timeline_view.LayoutForOverlappingIntervals(); 171} 172 173// Main view object for Boost handler timeline 174 175boost_asio_handler_timeline_view = new BoostASIOHandlerTimelineView(); 176boost_asio_handler_timeline_view.IsCanvasDirty = true; 177 178function draw_timeline_boost_asio_handler(ctx) { 179 boost_asio_handler_timeline_view.Render(ctx); 180} 181 182let Canvas_Asio = document.getElementById('my_canvas_boost_asio_handler'); 183 184Canvas_Asio.onmousemove = function(event) { 185 const v = boost_asio_handler_timeline_view; 186 v.MouseState.x = event.pageX - this.offsetLeft; 187 v.MouseState.y = event.pageY - this.offsetTop; 188 if (v.MouseState.pressed == true && 189 v.MouseState.hoveredSide == 'timeline') { // Update highlighted area 190 v.HighlightedRegion.t1 = v.MouseXToTimestamp(v.MouseState.x); 191 } 192 v.OnMouseMove(); 193 v.IsCanvasDirty = true; 194 195 v.linked_views.forEach(function(u) { 196 u.MouseState.x = event.pageX - Canvas_Asio.offsetLeft; 197 u.MouseState.y = 0; // Do not highlight any entry 198 if (u.MouseState.pressed == true && 199 u.MouseState.hoveredSide == 'timeline') { // Update highlighted area 200 u.HighlightedRegion.t1 = u.MouseXToTimestamp(u.MouseState.x); 201 } 202 u.OnMouseMove(); 203 u.IsCanvasDirty = true; 204 }); 205}; 206 207Canvas_Asio.onmousedown = function(event) { 208 if (event.button == 0) { 209 boost_asio_handler_timeline_view.OnMouseDown(); 210 } 211}; 212 213Canvas_Asio.onmouseup = function(event) { 214 if (event.button == 0) { 215 boost_asio_handler_timeline_view.OnMouseUp(); 216 } 217}; 218 219Canvas_Asio.onwheel = function(event) { 220 boost_asio_handler_timeline_view.OnMouseWheel(event); 221} 222