4 Test_shell has an optional tracing feature. It can be enabled by running
\r
5 with the --enable-tracing option. Tracing causes events to be dropped into
\r
6 a trace file during runtime.
\r
8 This HTML file can be used to render the output from the trace. You'll need
\r
9 to rename your trace data to "trace_data.js" in the same directory with this
\r
10 HTML file, and then you can visualize the trace.
\r
12 Lots of work remains on this tracing tool; currently development is on hold.
\r
23 font-family: "Courier New";
\r
31 border-bottom: 1px dashed black;
\r
32 background-color: #F0F0F0;
\r
48 background-color: #FFFFCC;
\r
50 font-family: "Courier New";
\r
53 border: 1px solid #CCCC88;
\r
62 border: 1px solid silver;
\r
64 background-color: #f0f0f0;
\r
79 background-color: #FFFFCC;
\r
94 border: 1px solid red;
\r
98 background-color: green;
\r
102 background-color: blue;
\r
106 background-color: black;
\r
110 background-color: orange;
\r
114 background-color: gray;
\r
118 background-color: blue;
\r
123 <script src='trace_data.js'></script>
\r
125 var scale = 100000;
\r
126 var row_height = 15;
\r
127 var trace_initial_time = 0;
\r
128 var trace_threads = {};
\r
129 var heartbeats = [];
\r
130 var trace_total_time = 0;
\r
132 function process_raw_events() {
\r
133 trace_initial_time = raw_trace_events[0].usec_begin;
\r
136 for (var i in raw_trace_events) {
\r
137 e = raw_trace_events[i];
\r
138 var trace_events = trace_threads["e.tid"];
\r
139 if (!trace_events) {
\r
141 trace_threads["e.tid"] = trace_events;
\r
143 if (e.name.indexOf("heartbeat.") == 0) {
\r
144 heartbeats.push(e);
\r
145 } else if (e.type == "BEGIN") {
\r
146 trace_events.push(e);
\r
148 } else if (e.type == "END") {
\r
149 for (var s in stack) {
\r
150 var begin = stack[s];
\r
151 if ((begin.id == e.id) && (begin.name == e.name) &&
\r
152 (begin.pid == e.pid) && (begin.tid == e.tid)) {
\r
153 begin.usec_end = e.usec_begin;
\r
154 begin.duration = begin.usec_end - begin.usec_begin;
\r
155 begin.extra += " " + e.extra;
\r
156 stack.splice(s, 1);
\r
160 } else if (e.type == "INSTANT") {
\r
161 trace_events.push(e);
\r
166 trace_total_time = e.usec_end - trace_initial_time;
\r
168 trace_total_time = e.usec_begin - trace_initial_time;
\r
171 function compute_scale() {
\r
172 var outer = document.getElementById("outer");
\r
173 scale = Math.floor(trace_total_time / (outer.offsetWidth - (row_height * 2)));
\r
176 function show_details(tid, i, event) {
\r
177 var trace_events = trace_threads["e.tid"];
\r
178 var inner = trace_events[i].name + " " +
\r
179 trace_events[i].duration / 1000 + "ms<br />" +
\r
180 trace_events[i].id + "<br />" +
\r
181 trace_events[i].extra + "<br />";
\r
182 var tooltip = document.getElementById("tooltip");
\r
183 tooltip.innerHTML = inner;
\r
185 event = window.event;
\r
186 tooltip.style.top = event.pageY + 3;
\r
187 tooltip.style.left = event.pageX + 3;
\r
188 tooltip.style.display = "block";
\r
191 function generate_time_scale() {
\r
192 var view_size = window.clientWidth;
\r
193 var body_size = document.body.scrollWidth;
\r
196 var step_ms = Math.floor(scale / 10); // ms per 100px
\r
197 var pow10 = Math.pow(10, Math.floor(Math.log(step_ms) / Math.log(10)));
\r
198 var round = .5 * pow10;
\r
199 step_ms = round * (Math.floor(step_ms / round)); // round to a multiple of round
\r
200 for (var i = step_ms; i < trace_total_time / 1000; i += step_ms) {
\r
201 var x = Math.floor(i * 1000 / scale);
\r
202 inner += "<li class='time_tick' style='left: " + x + "px'>" + i + "</li>";
\r
204 var time_scale = document.getElementById("time_scale");
\r
205 time_scale.innerHTML = inner;
\r
206 time_scale.style.width = document.body.scrollWidth;
\r
209 function generate_io_graph(trace_events, top) {
\r
210 var max_height = 200;
\r
211 var bucket_size = 50000; // millisecs
\r
214 var buckets = new Array();
\r
216 var max_bucket = 0;
\r
218 // Go through events and find all read samples.
\r
219 // Aggregate data into buckets.
\r
220 for (var i in trace_events) {
\r
221 var e = trace_events[i];
\r
222 if (e.name != "socket.read") {
\r
226 var bytes = parseInt(e.extra);
\r
229 var start_time = e.usec_begin - trace_initial_time;
\r
230 var mybucket = Math.floor(start_time / bucket_size);
\r
232 if (buckets[mybucket] == undefined) {
\r
233 buckets[mybucket] = 0;
\r
235 buckets[mybucket] += bytes;
\r
237 if (buckets[max_bucket] == undefined ||
\r
238 buckets[max_bucket] < buckets[mybucket]) {
\r
239 max_bucket = mybucket;
\r
243 for (var index = 0; index < buckets.length; index++) {
\r
244 var left = index * Math.floor(bucket_size / scale);
\r
245 var width = Math.floor(bucket_size / scale);
\r
250 if (buckets[index] == undefined) {
\r
253 height = (buckets[index] / buckets[max_bucket]) * max_height;
\r
256 var my_top = max_height - height;
\r
258 var style = "top: " + my_top + "px; left: " + left + "px; width: " + width + "px; height:" + height + "px;";
\r
260 inner += "<li title='" + buckets[index] + " bytes' class='" + cls + "' id='li-" + i + "' style='" + style + "'></li>\n";
\r
263 var subchart = document.createElement('div');
\r
264 subchart.setAttribute("class", "iograph");
\r
265 subchart.setAttribute("id", trace_events[0].tid);
\r
266 subchart.innerHTML = inner;
\r
267 subchart.style.height = max_height;
\r
268 subchart.style.top = top;
\r
269 subchart.style.left = 0;
\r
270 subchart.style.position = "absolute";
\r
271 // subchart.style.width = row_height + last_max_x;
\r
272 var chart = document.getElementById("chart");
\r
273 chart.appendChild(subchart);
\r
275 return top + max_height;
\r
278 function generate_subchart(trace_events, top) {
\r
279 var start_top = top;
\r
280 var heights = new Array();
\r
283 var last_max_time = 0;
\r
284 var last_max_x = 0;
\r
285 for (var i in trace_events) {
\r
286 var e = trace_events[i];
\r
287 var start_time = e.usec_begin - trace_initial_time;
\r
288 var left = row_height + Math.floor(start_time / scale);
\r
289 var width = Math.floor(e.duration / scale);
\r
293 if (heights[e.id]) {
\r
294 top = heights[e.id];
\r
296 max_row += row_height;
\r
297 heights[e.id] = max_row;
\r
298 top = heights[e.id];
\r
300 //if (start_time < last_max_time)
\r
301 // top += row_height;
\r
302 var style = "top: " + top + "px; left: " + left + "px; width: " + width + "px;";
\r
303 var js = 'javascript:show_details("' + e.tid + '", ' + i + ', event);';
\r
304 var cls = e.name.split('.')[0];
\r
305 inner += "<li class='" + cls + "' onmouseover='" + js + "' id='li-" + i + "' style='" + style + "'></li>\n";
\r
306 last_max_time = start_time + e.duration;
\r
307 last_max_x = left + width;
\r
309 var subchart = document.createElement('div');
\r
310 subchart.setAttribute("class", "subchart");
\r
311 subchart.setAttribute("id", trace_events[0].tid);
\r
312 subchart.innerHTML = inner;
\r
313 subchart.style.top = start_top + "px";
\r
314 subchart.style.height = top + row_height;
\r
315 subchart.style.width = row_height + last_max_x;
\r
316 subchart.style.position = "absolute";
\r
317 var chart = document.getElementById("chart");
\r
318 chart.appendChild(subchart);
\r
323 function generate_chart() {
\r
324 var chart = document.getElementById("chart");
\r
325 chart.innerHTML = "";
\r
327 for (var t in trace_threads) {
\r
328 top = generate_io_graph(trace_threads[t], top);
\r
329 top = generate_subchart(trace_threads[t], top);
\r
331 generate_time_scale();
\r
334 function change_scale(event) {
\r
336 event = window.event;
\r
337 if (!event.shiftKey)
\r
340 if (event.wheelDelta) {
\r
341 delta = event.wheelDelta / 120;
\r
342 } else if (event.detail) {
\r
343 delta = - event.detail / 3;
\r
346 var tooltip = document.getElementById("tooltip");
\r
347 tooltip.style.display = "none";
\r
350 scale = Math.floor(scale * factor);
\r
352 scale = Math.floor(scale / factor);
\r
353 if (scale > 300000)
\r
356 if (event.preventDefault)
\r
357 event.preventDefault();
\r
359 event.returnValue = false;
\r
362 function initial_load() {
\r
363 if (window.addEventListener)
\r
364 window.addEventListener('DOMMouseScroll', change_scale, false);
\r
365 window.onmousewheel = document.onmousewheel = change_scale;
\r
367 process_raw_events();
\r
374 <body onload='initial_load();'>
\r
376 <h2>Trace Events</h2>
\r
377 <div id="instructions">
\r
378 Use shift+mouse-wheel to zoom in and out.
\r
380 <div id="time_scale"></div>
\r
383 <span class="url"> </span> URL<br />
\r
384 <span class="http"> </span> HTTP<br />
\r
385 <span class="socket"> </span> Socket<br />
\r
386 <span class="v8"> </span> V8<br />
\r
387 <span class="loop"> </span> TASKS<br />
\r
393 <div id="tooltip" ondblclick="this.style.display = 'none';"></div>
\r