ruby-prof 1.4.4-x64-mingw-ucrt

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +608 -0
  3. data/LICENSE +25 -0
  4. data/README.md +5 -0
  5. data/Rakefile +98 -0
  6. data/bin/ruby-prof +328 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +22 -0
  9. data/ext/ruby_prof/rp_aggregate_call_tree.c +59 -0
  10. data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
  11. data/ext/ruby_prof/rp_allocation.c +287 -0
  12. data/ext/ruby_prof/rp_allocation.h +31 -0
  13. data/ext/ruby_prof/rp_call_tree.c +367 -0
  14. data/ext/ruby_prof/rp_call_tree.h +43 -0
  15. data/ext/ruby_prof/rp_call_trees.c +288 -0
  16. data/ext/ruby_prof/rp_call_trees.h +28 -0
  17. data/ext/ruby_prof/rp_measure_allocations.c +47 -0
  18. data/ext/ruby_prof/rp_measure_memory.c +46 -0
  19. data/ext/ruby_prof/rp_measure_process_time.c +66 -0
  20. data/ext/ruby_prof/rp_measure_wall_time.c +64 -0
  21. data/ext/ruby_prof/rp_measurement.c +237 -0
  22. data/ext/ruby_prof/rp_measurement.h +50 -0
  23. data/ext/ruby_prof/rp_method.c +491 -0
  24. data/ext/ruby_prof/rp_method.h +62 -0
  25. data/ext/ruby_prof/rp_profile.c +915 -0
  26. data/ext/ruby_prof/rp_profile.h +35 -0
  27. data/ext/ruby_prof/rp_stack.c +212 -0
  28. data/ext/ruby_prof/rp_stack.h +53 -0
  29. data/ext/ruby_prof/rp_thread.c +362 -0
  30. data/ext/ruby_prof/rp_thread.h +39 -0
  31. data/ext/ruby_prof/ruby_prof.c +52 -0
  32. data/ext/ruby_prof/ruby_prof.h +26 -0
  33. data/ext/ruby_prof/vc/ruby_prof.sln +39 -0
  34. data/ext/ruby_prof/vc/ruby_prof.vcxproj +160 -0
  35. data/lib/3.1/ruby_prof.so +0 -0
  36. data/lib/ruby-prof/assets/call_stack_printer.html.erb +711 -0
  37. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  38. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -0
  39. data/lib/ruby-prof/call_tree.rb +57 -0
  40. data/lib/ruby-prof/call_tree_visitor.rb +36 -0
  41. data/lib/ruby-prof/compatibility.rb +99 -0
  42. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  43. data/lib/ruby-prof/measurement.rb +17 -0
  44. data/lib/ruby-prof/method_info.rb +78 -0
  45. data/lib/ruby-prof/printers/abstract_printer.rb +137 -0
  46. data/lib/ruby-prof/printers/call_info_printer.rb +53 -0
  47. data/lib/ruby-prof/printers/call_stack_printer.rb +180 -0
  48. data/lib/ruby-prof/printers/call_tree_printer.rb +147 -0
  49. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  50. data/lib/ruby-prof/printers/flat_printer.rb +53 -0
  51. data/lib/ruby-prof/printers/graph_html_printer.rb +63 -0
  52. data/lib/ruby-prof/printers/graph_printer.rb +113 -0
  53. data/lib/ruby-prof/printers/multi_printer.rb +127 -0
  54. data/lib/ruby-prof/profile.rb +37 -0
  55. data/lib/ruby-prof/rack.rb +95 -0
  56. data/lib/ruby-prof/task.rb +147 -0
  57. data/lib/ruby-prof/thread.rb +20 -0
  58. data/lib/ruby-prof/version.rb +3 -0
  59. data/lib/ruby-prof.rb +52 -0
  60. data/lib/unprof.rb +10 -0
  61. data/ruby-prof.gemspec +64 -0
  62. data/test/abstract_printer_test.rb +26 -0
  63. data/test/alias_test.rb +122 -0
  64. data/test/basic_test.rb +43 -0
  65. data/test/call_tree_visitor_test.rb +32 -0
  66. data/test/call_trees_test.rb +66 -0
  67. data/test/duplicate_names_test.rb +32 -0
  68. data/test/dynamic_method_test.rb +67 -0
  69. data/test/enumerable_test.rb +21 -0
  70. data/test/exceptions_test.rb +24 -0
  71. data/test/exclude_methods_test.rb +151 -0
  72. data/test/exclude_threads_test.rb +53 -0
  73. data/test/fiber_test.rb +129 -0
  74. data/test/gc_test.rb +100 -0
  75. data/test/inverse_call_tree_test.rb +175 -0
  76. data/test/line_number_test.rb +158 -0
  77. data/test/marshal_test.rb +145 -0
  78. data/test/measure_allocations.rb +26 -0
  79. data/test/measure_allocations_test.rb +333 -0
  80. data/test/measure_memory_test.rb +688 -0
  81. data/test/measure_process_time_test.rb +1614 -0
  82. data/test/measure_times.rb +56 -0
  83. data/test/measure_wall_time_test.rb +426 -0
  84. data/test/multi_printer_test.rb +71 -0
  85. data/test/no_method_class_test.rb +15 -0
  86. data/test/pause_resume_test.rb +175 -0
  87. data/test/prime.rb +54 -0
  88. data/test/prime_script.rb +6 -0
  89. data/test/printer_call_stack_test.rb +27 -0
  90. data/test/printer_call_tree_test.rb +30 -0
  91. data/test/printer_flat_test.rb +99 -0
  92. data/test/printer_graph_html_test.rb +59 -0
  93. data/test/printer_graph_test.rb +40 -0
  94. data/test/printers_test.rb +141 -0
  95. data/test/printing_recursive_graph_test.rb +81 -0
  96. data/test/profile_test.rb +16 -0
  97. data/test/rack_test.rb +93 -0
  98. data/test/recursive_test.rb +430 -0
  99. data/test/singleton_test.rb +38 -0
  100. data/test/stack_printer_test.rb +64 -0
  101. data/test/start_stop_test.rb +109 -0
  102. data/test/test_helper.rb +13 -0
  103. data/test/thread_test.rb +144 -0
  104. data/test/unique_call_path_test.rb +136 -0
  105. data/test/yarv_test.rb +60 -0
  106. metadata +187 -0
@@ -0,0 +1,711 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
5
+ <title>ruby-prof call tree</title>
6
+ <style>
7
+ body {
8
+ font-size: 70%;
9
+ padding: 0;
10
+ margin: 5px;
11
+ margin-right: 0px;
12
+ margin-left: 0px;
13
+ background: #ffffff;
14
+ }
15
+
16
+ ul {
17
+ margin-left: 0px;
18
+ margin-top: 0px;
19
+ margin-bottom: 0px;
20
+ padding-left: 0px;
21
+ list-style-type: none;
22
+ font-weight: normal;
23
+ }
24
+
25
+ li {
26
+ margin-left: 11px;
27
+ padding: 0px;
28
+ white-space: nowrap;
29
+ border-top: 1px solid #cccccc;
30
+ border-left: 1px solid #cccccc;
31
+ border-bottom: none;
32
+ }
33
+
34
+ .thread {
35
+ margin-left: 11px;
36
+ background: #708090;
37
+ padding-top: 3px;
38
+ padding-left: 12px;
39
+ padding-bottom: 2px;
40
+ border-left: 1px solid #CCCCCC;
41
+ border-top: 1px solid #CCCCCC;
42
+ font-weight: bold;
43
+ }
44
+
45
+ .hidden {
46
+ display: none;
47
+ width: 0px;
48
+ height: 0px;
49
+ margin: 0px;
50
+ padding: 0px;
51
+ border-style: none;
52
+ }
53
+
54
+ .color01 {
55
+ background: #adbdeb
56
+ }
57
+
58
+ .color05 {
59
+ background: #9daddb
60
+ }
61
+
62
+ .color0 {
63
+ background: #8d9dcb
64
+ }
65
+
66
+ .color1 {
67
+ background: #89bccb
68
+ }
69
+
70
+ .color2 {
71
+ background: #56e3e7
72
+ }
73
+
74
+ .color3 {
75
+ background: #32cd70
76
+ }
77
+
78
+ .color4 {
79
+ background: #a3d53c
80
+ }
81
+
82
+ .color5 {
83
+ background: #c4cb34
84
+ }
85
+
86
+ .color6 {
87
+ background: #dcb66d
88
+ }
89
+
90
+ .color7 {
91
+ background: #cda59e
92
+ }
93
+
94
+ .color8 {
95
+ background: #be9d9c
96
+ }
97
+
98
+ .color9 {
99
+ background: #cf947a
100
+ }
101
+
102
+ #commands {
103
+ font-size: 10pt;
104
+ padding: 10px;
105
+ margin-left: 11px;
106
+ margin-bottom: 0px;
107
+ margin-top: 0px;
108
+ background: #708090;
109
+ border-top: 1px solid #cccccc;
110
+ border-left: 1px solid #cccccc;
111
+ border-bottom: none;
112
+ }
113
+
114
+ #titlebar {
115
+ font-size: 10pt;
116
+ padding: 10px;
117
+ margin-left: 11px;
118
+ margin-bottom: 0px;
119
+ margin-top: 10px;
120
+ background: #8090a0;
121
+ border-top: 1px solid #cccccc;
122
+ border-left: 1px solid #cccccc;
123
+ border-bottom: none;
124
+ }
125
+
126
+ #help {
127
+ font-size: 10pt;
128
+ padding: 10px;
129
+ margin-left: 11px;
130
+ margin-bottom: 0px;
131
+ margin-top: 0px;
132
+ background: #8090a0;
133
+ display: none;
134
+ border-top: 1px solid #cccccc;
135
+ border-left: 1px solid #cccccc;
136
+ border-bottom: none;
137
+ }
138
+
139
+ #sentinel {
140
+ height: 400px;
141
+ margin-left: 11px;
142
+ background: #8090a0;
143
+ border-top: 1px solid #cccccc;
144
+ border-left: 1px solid #cccccc;
145
+ border-bottom: none;
146
+ }
147
+
148
+ input {
149
+ margin-left: 10px;
150
+ }
151
+
152
+ .toggle {
153
+ background: url(data:image/png;base64,<%= base64_image %>) no-repeat left center;
154
+ float: left;
155
+ width: 9px;
156
+ height: 9px;
157
+ margin: 2px 1px 1px 1px;
158
+ }
159
+
160
+ .toggle.minus {
161
+ background-position: -9px 0;
162
+ }
163
+
164
+ .toggle.plus {
165
+ background-position: -18px 0;
166
+ }
167
+ </style>
168
+
169
+ <script type="text/javascript">
170
+ function rootNode()
171
+ {
172
+ return currentThread
173
+ }
174
+
175
+ function showUL(node, show)
176
+ {
177
+ Array.prototype.forEach.call(node.childNodes, function(child)
178
+ {
179
+ if (child.nodeName == 'LI')
180
+ toggle(child, show)
181
+ })
182
+ }
183
+
184
+ function findUlChild(li)
185
+ {
186
+ var ul = li.childNodes[2]
187
+ while (ul && ul.nodeName != "UL")
188
+ {
189
+ ul = ul.nextSibling
190
+ }
191
+ return ul
192
+ }
193
+
194
+ function isLeafNode(li)
195
+ {
196
+ var element = li.querySelector('a')
197
+ return element.classList.contains('empty')
198
+ }
199
+
200
+ function toggle(li, show)
201
+ {
202
+ if (isLeafNode(li))
203
+ return
204
+
205
+ var img = li.firstChild
206
+ img.className = 'toggle '
207
+ img.className += show ? 'minus' : 'plus'
208
+
209
+ var ul = findUlChild(li)
210
+ if (ul)
211
+ {
212
+ ul.style.display = show ? 'block' : 'none'
213
+ showUL(ul, true)
214
+ }
215
+ }
216
+
217
+ function toggleLI(li)
218
+ {
219
+ var img = li.firstChild
220
+ if (img.className.indexOf("minus") > -1)
221
+ toggle(li, false)
222
+ else
223
+ {
224
+ if (img.className.indexOf("plus") > -1)
225
+ toggle(li, true)
226
+ }
227
+ }
228
+
229
+ function aboveThreshold(text, threshold)
230
+ {
231
+ var match = text.match(/\d+[.,]\d+%/)
232
+ if (!match)
233
+ {
234
+ return true
235
+ }
236
+ else
237
+ {
238
+ var value = parseFloat(match[0].replace(/,/, '.'))
239
+ return value >= threshold
240
+ }
241
+ }
242
+
243
+ function setThresholdLI(li, threshold)
244
+ {
245
+ var a = li.querySelector('a')
246
+ var span = li.querySelector('span')
247
+ var ul = li.querySelector('ul')
248
+
249
+ var visible = aboveThreshold(span.textContent, threshold) ? 1 : 0
250
+
251
+ var count = 0
252
+ if (ul)
253
+ {
254
+ count = setThresholdUL(ul, threshold)
255
+ }
256
+
257
+ if (count > 0)
258
+ {
259
+ a.className = 'toggle minus'
260
+ }
261
+ else
262
+ {
263
+ a.className = 'toggle empty'
264
+ }
265
+
266
+ if (visible)
267
+ {
268
+ li.style.display = 'block'
269
+ } else
270
+ {
271
+ li.style.display = 'none'
272
+ }
273
+ return visible
274
+ }
275
+
276
+ function setThresholdUL(node, threshold)
277
+ {
278
+ var count = 0
279
+ Array.prototype.forEach.call(node.childNodes, function(child)
280
+ {
281
+ if (child.nodeName == 'LI')
282
+ count = count + setThresholdLI(child, threshold)
283
+ })
284
+
285
+ var visible = (count > 0) ? 1 : 0
286
+ if (visible)
287
+ {
288
+ node.style.display = 'block'
289
+ } else
290
+ {
291
+ node.style.display = 'none'
292
+ }
293
+ return visible
294
+ }
295
+
296
+ function toggleChildren(img, event)
297
+ {
298
+ event.cancelBubble = true
299
+ if (img.className.indexOf('empty') > -1)
300
+ return
301
+
302
+ var minus = (img.className.indexOf('minus') > -1)
303
+
304
+ if (minus)
305
+ {
306
+ img.className = 'toggle plus'
307
+ } else
308
+ img.className = 'toggle minus'
309
+
310
+ var li = img.parentNode
311
+ var ul = findUlChild(li)
312
+ if (ul)
313
+ {
314
+ if (minus)
315
+ ul.style.display = 'none'
316
+ else
317
+ ul.style.display = 'block'
318
+ }
319
+ if (minus)
320
+ moveSelectionIfNecessary(li)
321
+ }
322
+
323
+ function showChildren(li)
324
+ {
325
+ var img = li.firstChild
326
+ if (img.className.indexOf('empty') > -1)
327
+ return
328
+ img.className = 'toggle minus'
329
+
330
+ var ul = findUlChild(li)
331
+ if (ul)
332
+ {
333
+ ul.style.display = 'block'
334
+ }
335
+ }
336
+
337
+ function setThreshold()
338
+ {
339
+ var tv = document.getElementById("threshold").value
340
+ if (tv.match(/[0-9]+([.,][0-9]+)?/))
341
+ {
342
+ var f = parseFloat(tv.replace(/,/, '.'))
343
+ var threads = document.getElementsByName("thread")
344
+ var l = threads.length
345
+ for (var i = 0; i < l; i++)
346
+ {
347
+ setThresholdUL(threads[i], f)
348
+ }
349
+ var p = selectedNode
350
+ while (p && p.style.display == 'none')
351
+ p = p.parentNode.parentNode
352
+ if (p && p.nodeName == "LI")
353
+ selectNode(p)
354
+ } else
355
+ {
356
+ alert("Please specify a decimal number as threshold value!")
357
+ }
358
+ }
359
+
360
+ function expandAll(event)
361
+ {
362
+ toggleAll(event, true)
363
+ }
364
+
365
+ function collapseAll(event)
366
+ {
367
+ toggleAll(event, false)
368
+ selectNode(rootNode(), null)
369
+ }
370
+
371
+ function toggleAll(event, show)
372
+ {
373
+ event.cancelBubble = true
374
+ var threads = document.getElementsByName("thread")
375
+ var l = threads.length
376
+ for (var i = 0; i < l; i++)
377
+ {
378
+ showUL(threads[i], show)
379
+ }
380
+ }
381
+
382
+ function toggleHelp(node)
383
+ {
384
+ var help = document.getElementById("help")
385
+ if (node.value == "Show Help")
386
+ {
387
+ node.value = "Hide Help"
388
+ help.style.display = 'block'
389
+ } else
390
+ {
391
+ node.value = "Show Help"
392
+ help.style.display = 'none'
393
+ }
394
+ }
395
+
396
+ var selectedNode = null
397
+ var selectedColor = null
398
+ var selectedThread = null
399
+
400
+ function descendentOf(a, b)
401
+ {
402
+ while (a != b && b != null)
403
+ b = b.parentNode
404
+ return (a == b)
405
+ }
406
+
407
+ function moveSelectionIfNecessary(node)
408
+ {
409
+ if (descendentOf(node, selectedNode))
410
+ selectNode(node, null)
411
+ }
412
+
413
+ function selectNode(node, event)
414
+ {
415
+ if (event)
416
+ {
417
+ event.cancelBubble = true
418
+ thread = findThread(node)
419
+ selectThread(thread)
420
+ }
421
+ if (selectedNode)
422
+ {
423
+ selectedNode.style.background = selectedColor
424
+ }
425
+ selectedNode = node
426
+ selectedColor = node.style.background
427
+ selectedNode.style.background = "red"
428
+ selectedNode.scrollIntoView()
429
+ window.scrollBy(0, -400)
430
+ }
431
+
432
+ function moveUp()
433
+ {
434
+ move(selectedNode.previousSibling)
435
+ }
436
+
437
+ function moveDown()
438
+ {
439
+ move(selectedNode.nextSibling)
440
+ }
441
+
442
+ function move(p)
443
+ {
444
+ while (p && p.style.display == 'none')
445
+ p = p.nextSibling
446
+ if (p && p.nodeName == "LI")
447
+ {
448
+ selectNode(p, null)
449
+ }
450
+ }
451
+
452
+ function moveLeft()
453
+ {
454
+ var p = selectedNode.parentNode.parentNode
455
+ if (p && p.nodeName == "LI")
456
+ {
457
+ selectNode(p, null)
458
+ }
459
+ }
460
+
461
+ function moveRight()
462
+ {
463
+ if (!isLeafNode(selectedNode))
464
+ {
465
+ showChildren(selectedNode)
466
+ var ul = findUlChild(selectedNode)
467
+ if (ul)
468
+ {
469
+ selectNode(ul.firstChild, null)
470
+ }
471
+ }
472
+ }
473
+
474
+ function moveForward()
475
+ {
476
+ if (isLeafNode(selectedNode))
477
+ {
478
+ var p = selectedNode
479
+ while ((p.nextSibling == null || p.nextSibling.style.display == 'none') && p.nodeName == "LI")
480
+ {
481
+ p = p.parentNode.parentNode
482
+ }
483
+ if (p.nodeName == "LI")
484
+ selectNode(p.nextSibling, null)
485
+ } else
486
+ {
487
+ moveRight()
488
+ }
489
+ }
490
+
491
+ function isExpandedNode(li)
492
+ {
493
+ var img = li.firstChild
494
+ return (img.className.indexOf('minus') > -1)
495
+ }
496
+
497
+ function moveBackward()
498
+ {
499
+ var p = selectedNode
500
+ var q = p.previousSibling
501
+ while (q != null && q.style.display == 'none')
502
+ q = q.previousSibling
503
+ if (q == null)
504
+ {
505
+ p = p.parentNode.parentNode
506
+ } else
507
+ {
508
+ while (!isLeafNode(q) && isExpandedNode(q))
509
+ {
510
+ q = findUlChild(q).lastChild
511
+ while (q.style.display == 'none')
512
+ q = q.previousSibling
513
+ }
514
+ p = q
515
+ }
516
+ if (p.nodeName == "LI")
517
+ selectNode(p, null)
518
+ }
519
+
520
+ function moveHome()
521
+ {
522
+ selectNode(currentThread)
523
+ }
524
+
525
+ var currentThreadIndex = null
526
+
527
+ function findThread(node)
528
+ {
529
+ while (node && !node.parentNode.nodeName.match(/BODY|DIV/g))
530
+ {
531
+ node = node.parentNode
532
+ }
533
+ return node.firstChild
534
+ }
535
+
536
+ function selectThread(node)
537
+ {
538
+ var threads = document.getElementsByName("thread")
539
+ currentThread = node
540
+ for (var i = 0; i < threads.length; i++)
541
+ {
542
+ if (threads[i] == currentThread.parentNode)
543
+ currentThreadIndex = i
544
+ }
545
+ }
546
+
547
+ function nextThread()
548
+ {
549
+ var threads = document.getElementsByName("thread")
550
+ if (currentThreadIndex == threads.length - 1)
551
+ currentThreadIndex = 0
552
+ else
553
+ currentThreadIndex += 1
554
+ currentThread = threads[currentThreadIndex].firstChild
555
+ selectNode(currentThread, null)
556
+ }
557
+
558
+ function previousThread()
559
+ {
560
+ var threads = document.getElementsByName("thread")
561
+ if (currentThreadIndex == 0)
562
+ currentThreadIndex = threads.length - 1
563
+ else
564
+ currentThreadIndex -= 1
565
+ currentThread = threads[currentThreadIndex].firstChild
566
+ selectNode(currentThread, null)
567
+ }
568
+
569
+ function switchThread(node, event)
570
+ {
571
+ event.cancelBubble = true
572
+ selectThread(node.nextSibling.firstChild)
573
+ selectNode(currentThread, null)
574
+ }
575
+
576
+ function handleKeyEvent(event)
577
+ {
578
+ var code = event.charCode ? event.charCode : event.keyCode
579
+ var str = String.fromCharCode(code)
580
+ switch (str)
581
+ {
582
+ case "a":
583
+ moveLeft()
584
+ break
585
+ case "s":
586
+ moveDown()
587
+ break
588
+ case "d":
589
+ moveRight()
590
+ break
591
+ case "w":
592
+ moveUp()
593
+ break
594
+ case "f":
595
+ moveForward()
596
+ break
597
+ case "b":
598
+ moveBackward()
599
+ break
600
+ case "x":
601
+ toggleChildren(selectedNode.firstChild, event)
602
+ break
603
+ case "*":
604
+ toggleLI(selectedNode)
605
+ break
606
+ case "n":
607
+ nextThread()
608
+ break
609
+ case "h":
610
+ moveHome()
611
+ break
612
+ case "p":
613
+ previousThread()
614
+ break
615
+ }
616
+ }
617
+
618
+ document.onkeypress = function (event)
619
+ {
620
+ handleKeyEvent(event)
621
+ }
622
+
623
+ window.onload = function ()
624
+ {
625
+ var images = document.querySelectorAll(".toggle")
626
+ for (var i = 0; i < images.length; i++)
627
+ {
628
+ var img = images[i]
629
+ img.onclick = function (event)
630
+ {
631
+ toggleChildren(this, event)
632
+ return false
633
+ }
634
+ }
635
+ var divs = document.getElementsByTagName("div")
636
+ for (i = 0; i < divs.length; i++)
637
+ {
638
+ var div = divs[i]
639
+ if (div.className == "thread")
640
+ div.onclick = function (event)
641
+ {
642
+ switchThread(this, event)
643
+ }
644
+ }
645
+ var lis = document.getElementsByTagName("li")
646
+ for (var i = 0; i < lis.length; i++)
647
+ {
648
+ lis[i].onclick = function (event)
649
+ {
650
+ selectNode(this, event)
651
+ }
652
+ }
653
+
654
+ var threads = document.getElementsByName("thread")
655
+ currentThreadIndex = 0
656
+ currentThread = threads[0].querySelector('li')
657
+ selectNode(currentThread, null)
658
+ }
659
+ </script>
660
+
661
+ <% @overall_time = @result.threads.reduce(0) do |val, thread|
662
+ val += thread.total_time
663
+ end %>
664
+ </head>
665
+ <body>
666
+ <div style="display: inline-block;">
667
+ <div id="titlebar">
668
+ Call tree for application <strong><%= application %> <%= arguments %></strong><br/> Generated on <%= Time.now %>
669
+ with options <%= @options.inspect %><br/>
670
+ </div>
671
+ <div id="commands">
672
+ <span style="font-size: 11pt; font-weight: bold;">Threshold:</span>
673
+ <input value="1.0" size="3" id="threshold" type="text">
674
+ <input value="Apply" onclick="setThreshold();" type="submit">
675
+ <input value="Expand All" onclick="expandAll(event);" type="submit">
676
+ <input value="Collapse All" onclick="collapseAll(event);" type="submit">
677
+ <input value="Show Help" onclick="toggleHelp(this);" type="submit">
678
+ </div>
679
+ <ul style="display: none;" id="help">
680
+ <li>* indicates recursively called methods</li>
681
+ <li>Enter a decimal value <i>d</i> into the threshold field and click "Apply" to hide all nodes marked with time
682
+ values lower than <em>d</em>.
683
+ </li>
684
+ <li>Click on "Expand All" for full tree expansion.</li>
685
+ <li>Click on "Collapse All" to show only top level nodes.</li>
686
+ <li>Use a, s, d, w as in Quake or Urban Terror to navigate the tree.</li>
687
+ <li>Use f and b to navigate the tree in preorder forward and backwards.</li>
688
+ <li>Use x to toggle visibility of a subtree.</li>
689
+ <li>Use * to expand/collapse a whole subtree.</li>
690
+ <li>Use h to navigate to thread root.</li>
691
+ <li>Use n and p to navigate between threads.</li>
692
+ <li>Click on background to move focus to a subtree.</li>
693
+ </ul>
694
+
695
+ <% @result.threads.each do |thread| %>
696
+ <% thread_percent = 100 * (thread.total_time / @overall_time)
697
+ thread_info = "#{"%4.2f%%" % thread_percent} ~ #{@overall_time}" %>
698
+ <div class="thread">
699
+ <span>Thread: <%= thread.id %>, Fiber: <%= thread.fiber_id %> (<%= thread_info %>)</span>
700
+ <ul name="thread">
701
+ <% visited = Set.new
702
+ output = StringIO.new('')
703
+ print_stack(output, visited, thread.call_tree, thread.call_tree.total_time) %>
704
+ <%= output.string %>
705
+ </ul>
706
+ </div>
707
+ <% end %>
708
+ <div id="sentinel"></div>
709
+ </div>
710
+ </body>
711
+ </html>