- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / tools / tracing / trace.html
1 <!--\r
2 Tracing template\r
3 ----------------\r
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
7 \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
11 \r
12 Lots of work remains on this tracing tool; currently development is on hold.\r
13 \r
14 -->\r
15 \r
16 <html>\r
17 <head>\r
18 <title>\r
19 Trace Events\r
20 </title>\r
21 <style>\r
22 body {\r
23   font-family: "Courier New";\r
24   font-size: 9pt;\r
25 }\r
26 \r
27 #header {\r
28   position: absolute;\r
29   top: 0px;\r
30   left: 0px;\r
31   border-bottom: 1px dashed black;\r
32   background-color: #F0F0F0;\r
33   z-index: 3;\r
34 }\r
35 \r
36 #outer {\r
37   position: relative;\r
38   height: 200px;\r
39 }\r
40 \r
41 #time_scale {\r
42   height: 15px;\r
43   width: 100%;\r
44 }\r
45 \r
46 #tooltip {\r
47   position: absolute;\r
48   background-color: #FFFFCC;\r
49   display: none;\r
50   font-family: "Courier New";\r
51   font-size: 9pt;\r
52   padding: 5px;\r
53   border: 1px solid #CCCC88;\r
54   z-index: 3;\r
55 }\r
56 \r
57 #legend {\r
58   position: fixed;\r
59   left: 10px;\r
60   bottom: 10px;\r
61   padding: 5px;\r
62   border: 1px solid silver;\r
63   z-index: 10;\r
64   background-color: #f0f0f0;\r
65 }\r
66 \r
67 h2 {\r
68   margin: 5px;\r
69 }\r
70 \r
71 #instructions {\r
72   position: absolute;\r
73   top: \r
74   float: right;\r
75   display: none;\r
76 }\r
77 \r
78 li.time_tick {\r
79   background-color: #FFFFCC;\r
80   height: 15px;\r
81 }\r
82 \r
83 li {\r
84   background: pink;\r
85   position: absolute;\r
86   height: 10px;\r
87   list-style: none;\r
88   margin: 0px;\r
89   padding: 0px;\r
90   z-index: 2;\r
91 }\r
92 \r
93 li:hover {\r
94   border: 1px solid red;\r
95 }\r
96 \r
97 .url {\r
98   background-color: green;\r
99 }\r
100 \r
101 .http {\r
102   background-color: blue;\r
103 }\r
104 \r
105 .socket {\r
106   background-color: black;\r
107 }\r
108 \r
109 .v8 {\r
110   background-color: orange; \r
111 }\r
112 \r
113 .loop {\r
114   background-color: gray; \r
115 }\r
116 \r
117 .io {\r
118   background-color: blue;\r
119 }\r
120 \r
121 </style>\r
122 \r
123 <script src='trace_data.js'></script>\r
124 <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
131 \r
132 function process_raw_events() {\r
133   trace_initial_time = raw_trace_events[0].usec_begin;\r
134   var stack = [];\r
135   var e;\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
140       trace_events = [];\r
141       trace_threads["e.tid"] = trace_events;\r
142     }\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
147       stack.unshift(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
157           break;\r
158         } \r
159       }\r
160     } else if (e.type == "INSTANT") {\r
161       trace_events.push(e);\r
162       e.duration = 0;\r
163     }\r
164   }\r
165   if (e.usec_end)\r
166     trace_total_time = e.usec_end - trace_initial_time;\r
167   else\r
168     trace_total_time = e.usec_begin - trace_initial_time;\r
169 }\r
170 \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
174 };\r
175 \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
184   if (window.event)\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
189 };\r
190 \r
191 function generate_time_scale() {\r
192   var view_size = window.clientWidth;\r
193   var body_size = document.body.scrollWidth;\r
194   var inner = "";\r
195   \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
203   }\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
207 }\r
208 \r
209 function generate_io_graph(trace_events, top) {\r
210   var max_height = 200;\r
211   var bucket_size = 50000;  // millisecs\r
212 \r
213   var inner = "";\r
214   var buckets = new Array();\r
215   var value = 0;\r
216   var max_bucket = 0;\r
217 \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
223       continue;\r
224     }\r
225 \r
226     var bytes = parseInt(e.extra);\r
227 //    bytes = 400;\r
228 \r
229     var start_time = e.usec_begin - trace_initial_time;\r
230     var mybucket = Math.floor(start_time / bucket_size);\r
231 \r
232     if (buckets[mybucket] == undefined) {\r
233       buckets[mybucket] = 0;\r
234     }\r
235     buckets[mybucket] += bytes;\r
236 \r
237     if (buckets[max_bucket] == undefined || \r
238         buckets[max_bucket] < buckets[mybucket]) {\r
239       max_bucket = mybucket;\r
240     }\r
241   }\r
242 \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
246     if (width == 0)\r
247       width = 1;\r
248 \r
249     var height;\r
250     if (buckets[index] == undefined) {\r
251       height = 0;\r
252     } else {\r
253       height = (buckets[index] / buckets[max_bucket]) * max_height;\r
254     }\r
255 \r
256     var my_top = max_height - height;\r
257 \r
258     var style = "top: " + my_top + "px; left: " + left + "px; width: " + width + "px; height:" + height + "px;";\r
259     var cls = "io";\r
260     inner += "<li title='" + buckets[index] + " bytes' class='" + cls + "' id='li-" + i + "' style='" + style + "'></li>\n";\r
261   }\r
262 \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
274 \r
275   return top + max_height;\r
276 }\r
277 \r
278 function generate_subchart(trace_events, top) {\r
279   var start_top = top;\r
280   var heights = new Array();\r
281   var max_row = 0;\r
282   var inner = "";\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
290     if (width == 0)\r
291       width = 1;\r
292 \r
293     if (heights[e.id]) {\r
294       top = heights[e.id];\r
295     } else {\r
296       max_row += row_height;\r
297       heights[e.id] = max_row;\r
298       top = heights[e.id];\r
299     }\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
308   }\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
319   \r
320   return top;\r
321 };\r
322 \r
323 function generate_chart() {\r
324   var chart = document.getElementById("chart");\r
325   chart.innerHTML = "";\r
326   var top = 60;\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
330   }\r
331   generate_time_scale();\r
332 }\r
333 \r
334 function change_scale(event) {\r
335   if (!event)\r
336     event = window.event;\r
337   if (!event.shiftKey)\r
338     return;\r
339   var delta = 0;\r
340   if (event.wheelDelta) {\r
341     delta = event.wheelDelta / 120;\r
342   } else if (event.detail) {\r
343     delta = - event.detail / 3;\r
344   }\r
345   if (delta) {\r
346     var tooltip = document.getElementById("tooltip");\r
347     tooltip.style.display = "none";\r
348     var factor = 1.1;\r
349     if (delta < 0)\r
350       scale = Math.floor(scale * factor);\r
351     else\r
352       scale = Math.floor(scale / factor);\r
353     if (scale > 300000)\r
354       scale = 300000;\r
355     generate_chart();\r
356     if (event.preventDefault)\r
357       event.preventDefault();\r
358   }\r
359   event.returnValue = false;\r
360 };\r
361 \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
366 \r
367   process_raw_events();\r
368   compute_scale();\r
369   generate_chart();\r
370 };\r
371 \r
372 </script>\r
373 </head>\r
374 <body onload='initial_load();'>\r
375 <div id="header">\r
376 <h2>Trace Events</h2>\r
377 <div id="instructions">\r
378 Use shift+mouse-wheel to zoom in and out.\r
379 </div>\r
380 <div id="time_scale"></div>\r
381 </div>\r
382 <div id="legend">\r
383 <span class="url">&nbsp;</span> URL<br />\r
384 <span class="http">&nbsp;</span> HTTP<br />\r
385 <span class="socket">&nbsp;</span> Socket<br />\r
386 <span class="v8">&nbsp;</span> V8<br />\r
387 <span class="loop">&nbsp;</span> TASKS<br />\r
388 </div>\r
389 <div id="chart">\r
390 <div id="outer">\r
391 </div>\r
392 </div>\r
393 <div id="tooltip" ondblclick="this.style.display = 'none';"></div>\r
394 </body>\r
395 </html>\r