1 <html> 2 <head> 3 <title> 4 Trace Events 5 </title> 6 <style> 7 body { 8 font-family: "Courier New"; 9 font-size: 9pt; 10 } 11 12 #header { 13 position: absolute; 14 top: 0px; 15 left: 0px; 16 border-bottom: 1px dashed black; 17 background-color: #F0F0F0; 18 z-index: 3; 19 } 20 21 #outer { 22 position: relative; 23 height: 200px; 24 } 25 26 #time_scale { 27 height: 15px; 28 width: 100%; 29 } 30 31 #tooltip { 32 position: absolute; 33 background-color: #FFFFCC; 34 display: none; 35 font-family: "Courier New"; 36 font-size: 9pt; 37 padding: 5px; 38 border: 1px solid #CCCC88; 39 z-index: 3; 40 } 41 42 #legend { 43 position: fixed; 44 left: 10px; 45 bottom: 10px; 46 padding: 5px; 47 border: 1px solid silver; 48 z-index: 10; 49 background-color: #f0f0f0; 50 } 51 52 h2 { 53 margin: 5px; 54 } 55 56 #instructions { 57 position: absolute; 58 top: 59 float: right; 60 display: none; 61 } 62 63 li.time_tick { 64 background-color: #FFFFCC; 65 height: 15px; 66 } 67 68 li { 69 background: pink; 70 position: absolute; 71 height: 10px; 72 list-style: none; 73 margin: 0px; 74 padding: 0px; 75 z-index: 2; 76 } 77 78 li:hover { 79 border: 1px solid red; 80 } 81 82 .url { 83 background-color: green; 84 } 85 86 .http { 87 background-color: blue; 88 } 89 90 .socket { 91 background-color: black; 92 } 93 94 .v8 { 95 background-color: orange; 96 } 97 98 </style> 99 100 <script src='trace_data.js'></script> 101 <script> 102 var scale = 100000; 103 var row_height = 15; 104 var trace_initial_time = 0; 105 var trace_threads = {}; 106 var heartbeats = []; 107 var trace_total_time = 0; 108 109 function process_raw_events() { 110 trace_initial_time = raw_trace_events[0].usec_begin; 111 var stack = []; 112 var e; 113 for (var i in raw_trace_events) { 114 e = raw_trace_events[i]; 115 var trace_events = trace_threads["e.tid"]; 116 if (!trace_events) { 117 trace_events = []; 118 trace_threads["e.tid"] = trace_events; 119 } 120 if (e.name.indexOf("heartbeat.") == 0) { 121 heartbeats.push(e); 122 } else if (e.type == "BEGIN") { 123 trace_events.push(e); 124 stack.unshift(e); 125 } else if (e.type == "END") { 126 for (var s in stack) { 127 var begin = stack[s]; 128 if ((begin.id == e.id) && (begin.name == e.name) && 129 (begin.pid == e.pid) && (begin.tid == e.tid)) { 130 begin.usec_end = e.usec_begin; 131 begin.duration = begin.usec_end - begin.usec_begin; 132 stack.splice(s, 1); 133 break; 134 } 135 } 136 } else if (e.type == "INSTANT") { 137 trace_events.push(e); 138 e.duration = 0; 139 } 140 } 141 if (e.usec_end) 142 trace_total_time = e.usec_end - trace_initial_time; 143 else 144 trace_total_time = e.usec_begin - trace_initial_time; 145 } 146 147 function compute_scale() { 148 var outer = document.getElementById("outer"); 149 scale = Math.floor(trace_total_time / (outer.offsetWidth - (row_height * 2))); 150 }; 151 152 function show_details(tid, i, event) { 153 var trace_events = trace_threads["e.tid"]; 154 var inner = trace_events[i].name + " " + 155 trace_events[i].duration / 1000 + "ms<br />" + 156 trace_events[i].id + "<br />" + 157 trace_events[i].extra + "<br />"; 158 var tooltip = document.getElementById("tooltip"); 159 tooltip.innerHTML = inner; 160 if (window.event) 161 event = window.event; 162 tooltip.style.top = event.pageY + 3; 163 tooltip.style.left = event.pageX + 3; 164 tooltip.style.display = "block"; 165 }; 166 167 function generate_time_scale() { 168 var view_size = window.clientWidth; 169 var body_size = document.body.scrollWidth; 170 var inner = ""; 171 172 var step_ms = Math.floor(scale / 10); // ms per 100px 173 var pow10 = Math.pow(10, Math.floor(Math.log(step_ms) / Math.log(10))); 174 var round = .5 * pow10; 175 step_ms = round * (Math.floor(step_ms / round)); // round to a multiple of round 176 for (var i = step_ms; i < trace_total_time / 1000; i += step_ms) { 177 var x = Math.floor(i * 1000 / scale); 178 inner += "<li class='time_tick' style='left: " + x + "px'>" + i + "</li>"; 179 } 180 var time_scale = document.getElementById("time_scale"); 181 time_scale.innerHTML = inner; 182 time_scale.style.width = document.body.scrollWidth; 183 } 184 185 function generate_subchart(trace_events, top) { 186 var inner = ""; 187 var last_max_time = 0; 188 var last_max_x = 0; 189 for (var i in trace_events) { 190 var e = trace_events[i]; 191 var start_time = e.usec_begin - trace_initial_time; 192 var left = row_height + Math.floor(start_time / scale); 193 var width = Math.floor(e.duration / scale); 194 if (width == 0) 195 width = 1; 196 if (start_time < last_max_time) 197 top += row_height; 198 var style = "top: " + top + "px; left: " + left + "px; width: " + width + "px;"; 199 var js = 'javascript:show_details("' + e.tid + '", ' + i + ', event);'; 200 var cls = e.name.split('.')[0]; 201 inner += "<li class='" + cls + "' onmouseover='" + js + "' id='li-" + i + "' style='" + style + "'></li>\n"; 202 last_max_time = start_time + e.duration; 203 last_max_x = left + width; 204 } 205 var subchart = document.createElement('div'); 206 subchart.setAttribute("class", "subchart"); 207 subchart.setAttribute("id", trace_events[0].tid); 208 subchart.innerHTML = inner; 209 subchart.style.height = top + row_height; 210 subchart.style.width = row_height + last_max_x; 211 var chart = document.getElementById("chart"); 212 chart.appendChild(subchart); 213 214 return top; 215 }; 216 217 function generate_chart() { 218 var chart = document.getElementById("chart"); 219 chart.innerHTML = ""; 220 var top = 60; 221 for (var t in trace_threads) { 222 top = generate_subchart(trace_threads[t], top); 223 } 224 generate_time_scale(); 225 } 226 227 function change_scale(event) { 228 if (!event) 229 event = window.event; 230 if (!event.shiftKey) 231 return; 232 var delta = 0; 233 if (event.wheelDelta) { 234 delta = event.wheelDelta / 120; 235 } else if (event.detail) { 236 delta = - event.detail / 3; 237 } 238 if (delta) { 239 var tooltip = document.getElementById("tooltip"); 240 tooltip.style.display = "none"; 241 var factor = 1.1; 242 if (delta < 0) 243 scale = Math.floor(scale * factor); 244 else 245 scale = Math.floor(scale / factor); 246 if (scale > 300000) 247 scale = 300000; 248 generate_chart(); 249 if (event.preventDefault) 250 event.preventDefault(); 251 } 252 event.returnValue = false; 253 }; 254 255 function initial_load() { 256 if (window.addEventListener) 257 window.addEventListener('DOMMouseScroll', change_scale, false); 258 window.onmousewheel = document.onmousewheel = change_scale; 259 260 process_raw_events(); 261 compute_scale(); 262 generate_chart(); 263 }; 264 265 </script> 266 </head> 267 <body onload='initial_load();'> 268 <div id="header"> 269 <h2>Trace Events</h2> 270 <div id="instructions"> 271 Use shift+mouse-wheel to zoom in and out. 272 </div> 273 <div id="time_scale"></div> 274 </div> 275 <div id="legend"> 276 <span class="url"> </span> URL<br /> 277 <span class="http"> </span> HTTP<br /> 278 <span class="socket"> </span> Socket<br /> 279 <span class="v8"> </span> V8<br /> 280 </div> 281 <div id="chart"> 282 <div id="outer"> 283 </div> 284 </div> 285 <div id="tooltip" ondblclick="this.style.display = 'none';"></div> 286 </body> 287 </html> 288