• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!--
2Tracing template
3----------------
4Test_shell has an optional tracing feature.  It can be enabled by running
5with the --enable-tracing option.  Tracing causes events to be dropped into
6a trace file during runtime.
7
8This HTML file can be used to render the output from the trace.  You'll need
9to rename your trace data to "trace_data.js" in the same directory with this
10HTML file, and then you can visualize the trace.
11
12Lots of work remains on this tracing tool; currently development is on hold.
13
14-->
15
16<html>
17<head>
18<title>
19Trace Events
20</title>
21<style>
22body {
23  font-family: "Courier New";
24  font-size: 9pt;
25}
26
27#header {
28  position: absolute;
29  top: 0px;
30  left: 0px;
31  border-bottom: 1px dashed black;
32  background-color: #F0F0F0;
33  z-index: 3;
34}
35
36#outer {
37  position: relative;
38  height: 200px;
39}
40
41#time_scale {
42  height: 15px;
43  width: 100%;
44}
45
46#tooltip {
47  position: absolute;
48  background-color: #FFFFCC;
49  display: none;
50  font-family: "Courier New";
51  font-size: 9pt;
52  padding: 5px;
53  border: 1px solid #CCCC88;
54  z-index: 3;
55}
56
57#legend {
58  position: fixed;
59  left: 10px;
60  bottom: 10px;
61  padding: 5px;
62  border: 1px solid silver;
63  z-index: 10;
64  background-color: #f0f0f0;
65}
66
67h2 {
68  margin: 5px;
69}
70
71#instructions {
72  position: absolute;
73  top:
74  float: right;
75  display: none;
76}
77
78li.time_tick {
79  background-color: #FFFFCC;
80  height: 15px;
81}
82
83li {
84  background: pink;
85  position: absolute;
86  height: 10px;
87  list-style: none;
88  margin: 0px;
89  padding: 0px;
90  z-index: 2;
91}
92
93li:hover {
94  border: 1px solid red;
95}
96
97.url {
98  background-color: green;
99}
100
101.http {
102  background-color: blue;
103}
104
105.socket {
106  background-color: black;
107}
108
109.v8 {
110  background-color: orange;
111}
112
113.loop {
114  background-color: gray;
115}
116
117.io {
118  background-color: blue;
119}
120
121</style>
122
123<script src='trace_data.js'></script>
124<script>
125var scale = 100000;
126var row_height = 15;
127var trace_initial_time = 0;
128var trace_threads = {};
129var heartbeats = [];
130var trace_total_time = 0;
131
132function process_raw_events() {
133  trace_initial_time = raw_trace_events[0].usec_begin;
134  var stack = [];
135  var e;
136  for (var i in raw_trace_events) {
137    e = raw_trace_events[i];
138    var trace_events = trace_threads["e.tid"];
139    if (!trace_events) {
140      trace_events = [];
141      trace_threads["e.tid"] = trace_events;
142    }
143    if (e.name.indexOf("heartbeat.") == 0) {
144      heartbeats.push(e);
145    } else if (e.type == "BEGIN") {
146      trace_events.push(e);
147      stack.unshift(e);
148    } else if (e.type == "END") {
149      for (var s in stack) {
150        var begin = stack[s];
151        if ((begin.id == e.id) && (begin.name == e.name) &&
152            (begin.pid == e.pid) && (begin.tid == e.tid)) {
153          begin.usec_end = e.usec_begin;
154          begin.duration = begin.usec_end - begin.usec_begin;
155          begin.extra += " " + e.extra;
156          stack.splice(s, 1);
157          break;
158        }
159      }
160    } else if (e.type == "INSTANT") {
161      trace_events.push(e);
162      e.duration = 0;
163    }
164  }
165  if (e.usec_end)
166    trace_total_time = e.usec_end - trace_initial_time;
167  else
168    trace_total_time = e.usec_begin - trace_initial_time;
169}
170
171function compute_scale() {
172  var outer = document.getElementById("outer");
173  scale = Math.floor(trace_total_time / (outer.offsetWidth - (row_height * 2)));
174};
175
176function show_details(tid, i, event) {
177  var trace_events = trace_threads["e.tid"];
178  var inner = trace_events[i].name + " " +
179              trace_events[i].duration / 1000 + "ms<br />" +
180              trace_events[i].id  + "<br />" +
181              trace_events[i].extra  + "<br />";
182  var tooltip = document.getElementById("tooltip");
183  tooltip.innerHTML = inner;
184  if (window.event)
185    event = window.event;
186  tooltip.style.top = event.pageY + 3;
187  tooltip.style.left = event.pageX + 3;
188  tooltip.style.display = "block";
189};
190
191function generate_time_scale() {
192  var view_size = window.clientWidth;
193  var body_size = document.body.scrollWidth;
194  var inner = "";
195
196  var step_ms = Math.floor(scale / 10); // ms per 100px
197  var pow10 = Math.pow(10, Math.floor(Math.log(step_ms) / Math.log(10)));
198  var round = .5 * pow10;
199  step_ms = round * (Math.floor(step_ms / round)); // round to a multiple of round
200  for (var i = step_ms; i < trace_total_time / 1000; i += step_ms) {
201    var x = Math.floor(i * 1000 / scale);
202    inner += "<li class='time_tick' style='left: " + x + "px'>" + i + "</li>";
203  }
204  var time_scale = document.getElementById("time_scale");
205  time_scale.innerHTML = inner;
206  time_scale.style.width = document.body.scrollWidth;
207}
208
209function generate_io_graph(trace_events, top) {
210  var max_height = 200;
211  var bucket_size = 50000;  // millisecs
212
213  var inner = "";
214  var buckets = new Array();
215  var value = 0;
216  var max_bucket = 0;
217
218  // Go through events and find all read samples.
219  // Aggregate data into buckets.
220  for (var i in trace_events) {
221    var e = trace_events[i];
222    if (e.name != "socket.read") {
223      continue;
224    }
225
226    var bytes = parseInt(e.extra);
227//    bytes = 400;
228
229    var start_time = e.usec_begin - trace_initial_time;
230    var mybucket = Math.floor(start_time / bucket_size);
231
232    if (buckets[mybucket] == undefined) {
233      buckets[mybucket] = 0;
234    }
235    buckets[mybucket] += bytes;
236
237    if (buckets[max_bucket] == undefined ||
238        buckets[max_bucket] < buckets[mybucket]) {
239      max_bucket = mybucket;
240    }
241  }
242
243  for (var index = 0; index < buckets.length; index++) {
244    var left = index * Math.floor(bucket_size / scale);
245    var width = Math.floor(bucket_size / scale);
246    if (width == 0)
247      width = 1;
248
249    var height;
250    if (buckets[index] == undefined) {
251      height = 0;
252    } else {
253      height = (buckets[index] / buckets[max_bucket]) * max_height;
254    }
255
256    var my_top = max_height - height;
257
258    var style = "top: " + my_top + "px; left: " + left + "px; width: " + width + "px; height:" + height + "px;";
259    var cls = "io";
260    inner += "<li title='" + buckets[index] + " bytes' class='" + cls + "' id='li-" + i + "' style='" + style + "'></li>\n";
261  }
262
263  var subchart = document.createElement('div');
264  subchart.setAttribute("class", "iograph");
265  subchart.setAttribute("id", trace_events[0].tid);
266  subchart.innerHTML = inner;
267  subchart.style.height = max_height;
268  subchart.style.top = top;
269  subchart.style.left = 0;
270  subchart.style.position = "absolute";
271//  subchart.style.width = row_height + last_max_x;
272  var chart = document.getElementById("chart");
273  chart.appendChild(subchart);
274
275  return top + max_height;
276}
277
278function generate_subchart(trace_events, top) {
279  var start_top = top;
280  var heights = new Array();
281  var max_row = 0;
282  var inner = "";
283  var last_max_time = 0;
284  var last_max_x = 0;
285  for (var i in trace_events) {
286    var e = trace_events[i];
287    var start_time = e.usec_begin - trace_initial_time;
288    var left = row_height + Math.floor(start_time / scale);
289    var width = Math.floor(e.duration / scale);
290    if (width == 0)
291      width = 1;
292
293    if (heights[e.id]) {
294      top = heights[e.id];
295    } else {
296      max_row += row_height;
297      heights[e.id] = max_row;
298      top = heights[e.id];
299    }
300    //if (start_time < last_max_time)
301    //  top += row_height;
302    var style = "top: " + top + "px; left: " + left + "px; width: " + width + "px;";
303    var js = 'javascript:show_details("' + e.tid + '", ' + i + ', event);';
304    var cls = e.name.split('.')[0];
305    inner += "<li class='" + cls + "' onmouseover='" + js + "' id='li-" + i + "' style='" + style + "'></li>\n";
306    last_max_time = start_time + e.duration;
307    last_max_x = left + width;
308  }
309  var subchart = document.createElement('div');
310  subchart.setAttribute("class", "subchart");
311  subchart.setAttribute("id", trace_events[0].tid);
312  subchart.innerHTML = inner;
313  subchart.style.top = start_top + "px";
314  subchart.style.height = top + row_height;
315  subchart.style.width = row_height + last_max_x;
316  subchart.style.position = "absolute";
317  var chart = document.getElementById("chart");
318  chart.appendChild(subchart);
319
320  return top;
321};
322
323function generate_chart() {
324  var chart = document.getElementById("chart");
325  chart.innerHTML = "";
326  var top = 60;
327  for (var t in trace_threads) {
328    top = generate_io_graph(trace_threads[t], top);
329    top = generate_subchart(trace_threads[t], top);
330  }
331  generate_time_scale();
332}
333
334function change_scale(event) {
335  if (!event)
336    event = window.event;
337  if (!event.shiftKey)
338    return;
339  var delta = 0;
340  if (event.wheelDelta) {
341    delta = event.wheelDelta / 120;
342  } else if (event.detail) {
343    delta = - event.detail / 3;
344  }
345  if (delta) {
346    var tooltip = document.getElementById("tooltip");
347    tooltip.style.display = "none";
348    var factor = 1.1;
349    if (delta < 0)
350      scale = Math.floor(scale * factor);
351    else
352      scale = Math.floor(scale / factor);
353    if (scale > 300000)
354      scale = 300000;
355    generate_chart();
356    if (event.preventDefault)
357      event.preventDefault();
358  }
359  event.returnValue = false;
360};
361
362function initial_load() {
363  if (window.addEventListener)
364    window.addEventListener('DOMMouseScroll', change_scale, false);
365  window.onmousewheel = document.onmousewheel = change_scale;
366
367  process_raw_events();
368  compute_scale();
369  generate_chart();
370};
371
372</script>
373</head>
374<body onload='initial_load();'>
375<div id="header">
376<h2>Trace Events</h2>
377<div id="instructions">
378Use shift+mouse-wheel to zoom in and out.
379</div>
380<div id="time_scale"></div>
381</div>
382<div id="legend">
383<span class="url">&nbsp;</span> URL<br />
384<span class="http">&nbsp;</span> HTTP<br />
385<span class="socket">&nbsp;</span> Socket<br />
386<span class="v8">&nbsp;</span> V8<br />
387<span class="loop">&nbsp;</span> TASKS<br />
388</div>
389<div id="chart">
390<div id="outer">
391</div>
392</div>
393<div id="tooltip" ondblclick="this.style.display = 'none';"></div>
394</body>
395</html>
396