4 Test_shell has an optional tracing feature. It can be enabled by running
5 with the --enable-tracing option. Tracing causes events to be dropped into
6 a trace file during runtime.
8 This HTML file can be used to render the output from the trace. You'll need
9 to rename your trace data to "trace_data.js" in the same directory with this
10 HTML file, and then you can visualize the trace.
12 Lots of work remains on this tracing tool; currently development is on hold.
23 font-family:
"Courier New";
31 border-bottom:
1px dashed black;
32 background-color: #F0F0F0;
48 background-color: #FFFFCC;
50 font-family:
"Courier New";
53 border:
1px solid #CCCC88;
62 border:
1px solid silver;
64 background-color: #f0f0f0;
79 background-color: #FFFFCC;
94 border:
1px solid red;
98 background-color: green;
102 background-color: blue;
106 background-color: black;
110 background-color: orange;
114 background-color: gray;
118 background-color: blue;
123 <script src='trace_data.js'
></script>
127 var trace_initial_time
= 0;
128 var trace_threads
= {};
130 var trace_total_time
= 0;
132 function process_raw_events() {
133 trace_initial_time
= raw_trace_events
[0].usec_begin
;
136 for (var i
in raw_trace_events
) {
137 e
= raw_trace_events
[i
];
138 var trace_events
= trace_threads
["e.tid"];
141 trace_threads
["e.tid"] = trace_events
;
143 if (e
.name
.indexOf("heartbeat.") == 0) {
145 } else if (e
.type
== "BEGIN") {
146 trace_events
.push(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
;
160 } else if (e
.type
== "INSTANT") {
161 trace_events
.push(e
);
166 trace_total_time
= e
.usec_end
- trace_initial_time
;
168 trace_total_time
= e
.usec_begin
- trace_initial_time
;
171 function compute_scale() {
172 var outer
= document
.getElementById("outer");
173 scale
= Math
.floor(trace_total_time
/ (outer
.offsetWidth
- (row_height
* 2)));
176 function 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
;
185 event
= window
.event
;
186 tooltip
.style
.top
= event
.pageY
+ 3;
187 tooltip
.style
.left
= event
.pageX
+ 3;
188 tooltip
.style
.display
= "block";
191 function generate_time_scale() {
192 var view_size
= window
.clientWidth
;
193 var body_size
= document
.body
.scrollWidth
;
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>";
204 var time_scale
= document
.getElementById("time_scale");
205 time_scale
.innerHTML
= inner
;
206 time_scale
.style
.width
= document
.body
.scrollWidth
;
209 function generate_io_graph(trace_events
, top
) {
210 var max_height
= 200;
211 var bucket_size
= 50000; // millisecs
214 var buckets
= new Array();
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") {
226 var bytes
= parseInt(e
.extra
);
229 var start_time
= e
.usec_begin
- trace_initial_time
;
230 var mybucket
= Math
.floor(start_time
/ bucket_size
);
232 if (buckets
[mybucket
] == undefined) {
233 buckets
[mybucket
] = 0;
235 buckets
[mybucket
] += bytes
;
237 if (buckets
[max_bucket
] == undefined ||
238 buckets
[max_bucket
] < buckets
[mybucket
]) {
239 max_bucket
= mybucket
;
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
);
250 if (buckets
[index
] == undefined) {
253 height
= (buckets
[index
] / buckets
[max_bucket
]) * max_height
;
256 var my_top
= max_height
- height
;
258 var style
= "top: " + my_top
+ "px; left: " + left
+ "px; width: " + width
+ "px; height:" + height
+ "px;";
260 inner
+= "<li title='" + buckets
[index
] + " bytes' class='" + cls
+ "' id='li-" + i
+ "' style='" + style
+ "'></li>\n";
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
);
275 return top
+ max_height
;
278 function generate_subchart(trace_events
, top
) {
280 var heights
= new Array();
283 var last_max_time
= 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
);
296 max_row
+= row_height
;
297 heights
[e
.id
] = max_row
;
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
;
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
);
323 function generate_chart() {
324 var chart
= document
.getElementById("chart");
325 chart
.innerHTML
= "";
327 for (var t
in trace_threads
) {
328 top
= generate_io_graph(trace_threads
[t
], top
);
329 top
= generate_subchart(trace_threads
[t
], top
);
331 generate_time_scale();
334 function change_scale(event
) {
336 event
= window
.event
;
340 if (event
.wheelDelta
) {
341 delta
= event
.wheelDelta
/ 120;
342 } else if (event
.detail
) {
343 delta
= - event
.detail
/ 3;
346 var tooltip
= document
.getElementById("tooltip");
347 tooltip
.style
.display
= "none";
350 scale
= Math
.floor(scale
* factor
);
352 scale
= Math
.floor(scale
/ factor
);
356 if (event
.preventDefault
)
357 event
.preventDefault();
359 event
.returnValue
= false;
362 function initial_load() {
363 if (window
.addEventListener
)
364 window
.addEventListener('DOMMouseScroll', change_scale
, false);
365 window
.onmousewheel
= document
.onmousewheel
= change_scale
;
367 process_raw_events();
374 <body onload='initial_load();'
>
376 <h2>Trace Events
</h2>
377 <div id=
"instructions">
378 Use shift+mouse-wheel to zoom in and out.
380 <div id=
"time_scale"></div>
383 <span class=
"url"> </span> URL
<br />
384 <span class=
"http"> </span> HTTP
<br />
385 <span class=
"socket"> </span> Socket
<br />
386 <span class=
"v8"> </span> V8
<br />
387 <span class=
"loop"> </span> TASKS
<br />
393 <div id=
"tooltip" ondblclick=
"this.style.display = 'none';"></div>