ruby-prof 0.18.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +500 -0
  3. data/LICENSE +25 -0
  4. data/README.rdoc +487 -0
  5. data/Rakefile +113 -0
  6. data/bin/ruby-prof +345 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/examples/flat.txt +50 -0
  9. data/examples/graph.dot +84 -0
  10. data/examples/graph.html +823 -0
  11. data/examples/graph.txt +139 -0
  12. data/examples/multi.flat.txt +23 -0
  13. data/examples/multi.graph.html +760 -0
  14. data/examples/multi.grind.dat +114 -0
  15. data/examples/multi.stack.html +547 -0
  16. data/examples/stack.html +547 -0
  17. data/ext/ruby_prof/extconf.rb +68 -0
  18. data/ext/ruby_prof/rp_call_info.c +425 -0
  19. data/ext/ruby_prof/rp_call_info.h +53 -0
  20. data/ext/ruby_prof/rp_measure.c +40 -0
  21. data/ext/ruby_prof/rp_measure.h +45 -0
  22. data/ext/ruby_prof/rp_measure_allocations.c +76 -0
  23. data/ext/ruby_prof/rp_measure_cpu_time.c +136 -0
  24. data/ext/ruby_prof/rp_measure_gc_runs.c +73 -0
  25. data/ext/ruby_prof/rp_measure_gc_time.c +60 -0
  26. data/ext/ruby_prof/rp_measure_memory.c +77 -0
  27. data/ext/ruby_prof/rp_measure_process_time.c +71 -0
  28. data/ext/ruby_prof/rp_measure_wall_time.c +45 -0
  29. data/ext/ruby_prof/rp_method.c +630 -0
  30. data/ext/ruby_prof/rp_method.h +75 -0
  31. data/ext/ruby_prof/rp_stack.c +173 -0
  32. data/ext/ruby_prof/rp_stack.h +63 -0
  33. data/ext/ruby_prof/rp_thread.c +277 -0
  34. data/ext/ruby_prof/rp_thread.h +27 -0
  35. data/ext/ruby_prof/ruby_prof.c +794 -0
  36. data/ext/ruby_prof/ruby_prof.h +60 -0
  37. data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
  38. data/ext/ruby_prof/vc/ruby_prof.vcxproj +141 -0
  39. data/lib/2.6.3/ruby_prof.so +0 -0
  40. data/lib/ruby-prof.rb +68 -0
  41. data/lib/ruby-prof/aggregate_call_info.rb +76 -0
  42. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  43. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  44. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  45. data/lib/ruby-prof/call_info.rb +115 -0
  46. data/lib/ruby-prof/call_info_visitor.rb +40 -0
  47. data/lib/ruby-prof/compatibility.rb +179 -0
  48. data/lib/ruby-prof/method_info.rb +121 -0
  49. data/lib/ruby-prof/printers/abstract_printer.rb +104 -0
  50. data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
  51. data/lib/ruby-prof/printers/call_stack_printer.rb +265 -0
  52. data/lib/ruby-prof/printers/call_tree_printer.rb +143 -0
  53. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  54. data/lib/ruby-prof/printers/flat_printer.rb +70 -0
  55. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +83 -0
  56. data/lib/ruby-prof/printers/graph_html_printer.rb +249 -0
  57. data/lib/ruby-prof/printers/graph_printer.rb +116 -0
  58. data/lib/ruby-prof/printers/multi_printer.rb +84 -0
  59. data/lib/ruby-prof/profile.rb +26 -0
  60. data/lib/ruby-prof/profile/exclude_common_methods.rb +207 -0
  61. data/lib/ruby-prof/profile/legacy_method_elimination.rb +50 -0
  62. data/lib/ruby-prof/rack.rb +174 -0
  63. data/lib/ruby-prof/task.rb +147 -0
  64. data/lib/ruby-prof/thread.rb +35 -0
  65. data/lib/ruby-prof/version.rb +3 -0
  66. data/lib/unprof.rb +10 -0
  67. data/ruby-prof.gemspec +58 -0
  68. data/test/abstract_printer_test.rb +53 -0
  69. data/test/aggregate_test.rb +136 -0
  70. data/test/basic_test.rb +128 -0
  71. data/test/block_test.rb +74 -0
  72. data/test/call_info_test.rb +78 -0
  73. data/test/call_info_visitor_test.rb +31 -0
  74. data/test/duplicate_names_test.rb +32 -0
  75. data/test/dynamic_method_test.rb +55 -0
  76. data/test/enumerable_test.rb +21 -0
  77. data/test/exceptions_test.rb +24 -0
  78. data/test/exclude_methods_test.rb +146 -0
  79. data/test/exclude_threads_test.rb +53 -0
  80. data/test/fiber_test.rb +79 -0
  81. data/test/issue137_test.rb +63 -0
  82. data/test/line_number_test.rb +80 -0
  83. data/test/measure_allocations_test.rb +26 -0
  84. data/test/measure_cpu_time_test.rb +212 -0
  85. data/test/measure_gc_runs_test.rb +32 -0
  86. data/test/measure_gc_time_test.rb +36 -0
  87. data/test/measure_memory_test.rb +33 -0
  88. data/test/measure_process_time_test.rb +61 -0
  89. data/test/measure_wall_time_test.rb +255 -0
  90. data/test/method_elimination_test.rb +84 -0
  91. data/test/module_test.rb +45 -0
  92. data/test/multi_printer_test.rb +104 -0
  93. data/test/no_method_class_test.rb +15 -0
  94. data/test/pause_resume_test.rb +166 -0
  95. data/test/prime.rb +54 -0
  96. data/test/printers_test.rb +275 -0
  97. data/test/printing_recursive_graph_test.rb +127 -0
  98. data/test/rack_test.rb +157 -0
  99. data/test/recursive_test.rb +215 -0
  100. data/test/singleton_test.rb +38 -0
  101. data/test/stack_printer_test.rb +77 -0
  102. data/test/stack_test.rb +138 -0
  103. data/test/start_stop_test.rb +112 -0
  104. data/test/test_helper.rb +267 -0
  105. data/test/thread_test.rb +187 -0
  106. data/test/unique_call_path_test.rb +202 -0
  107. data/test/yarv_test.rb +55 -0
  108. metadata +199 -0
@@ -0,0 +1,385 @@
1
+ <script type="text/javascript">
2
+ /*
3
+ Copyright (C) 2005,2009 Stefan Kaes
4
+ skaes@railsexpress.de
5
+ */
6
+
7
+ function rootNode() {
8
+ return currentThread;
9
+ }
10
+
11
+ function showUL(node, show) {
12
+ var lis = node.childNodes;
13
+ var l = lis.length;
14
+ for (var i=0; i < l ; i++ ) {
15
+ toggle(lis[i], show);
16
+ }
17
+ }
18
+
19
+ function findUlChild(li){
20
+ var ul = li.childNodes[2];
21
+ while (ul && ul.nodeName != "UL") {
22
+ ul = ul.nextSibling;
23
+ }
24
+ return ul;
25
+ }
26
+
27
+ function isLeafNode(li) {
28
+ var img = li.firstChild;
29
+ return (img.className.indexOf('empty') > -1);
30
+ }
31
+
32
+ function toggle(li, show) {
33
+ if (isLeafNode(li))
34
+ return;
35
+
36
+ var img = li.firstChild;
37
+ img.className = 'toggle ';
38
+ img.className += show ? 'minus' : 'plus';
39
+
40
+ var ul = findUlChild(li);
41
+ if (ul) {
42
+ ul.style.display = show ? 'block' : 'none';
43
+ showUL(ul, true);
44
+ }
45
+ }
46
+
47
+ function toggleLI(li) {
48
+ var img = li.firstChild;
49
+ if (img.className.indexOf("minus")>-1)
50
+ toggle(li, false);
51
+ else {
52
+ if (img.className.indexOf("plus")>-1)
53
+ toggle(li, true);
54
+ }
55
+ }
56
+
57
+ function aboveThreshold(text, threshold) {
58
+ var match = text.match(/\d+[.,]\d+/);
59
+ return (match && parseFloat(match[0].replace(/,/, '.'))>=threshold);
60
+ }
61
+
62
+ function setThresholdLI(li, threshold) {
63
+ var img = li.firstChild;
64
+ var text = img.nextSibling.firstChild;
65
+ var ul = findUlChild(li);
66
+
67
+ var visible = aboveThreshold(text.nodeValue, threshold) ? 1 : 0;
68
+
69
+ var count = 0;
70
+ if (ul) {
71
+ count = setThresholdUL(ul, threshold);
72
+ }
73
+ if (count>0) {
74
+ img.className = 'toggle minus';
75
+ }
76
+ else {
77
+ img.className = 'toggle empty';
78
+ }
79
+ if (visible) {
80
+ li.style.display = 'block'
81
+ }
82
+ else {
83
+ li.style.display = 'none'
84
+ }
85
+ return visible;
86
+ }
87
+
88
+ function setThresholdUL(node, threshold) {
89
+ var lis = node.childNodes;
90
+ var l = lis.length;
91
+
92
+ var count = 0;
93
+ for ( var i = 0; i < l ; i++ ) {
94
+ count = count + setThresholdLI(lis[i], threshold);
95
+ }
96
+
97
+ var visible = (count > 0) ? 1 : 0;
98
+ if (visible) {
99
+ node.style.display = 'block';
100
+ }
101
+ else {
102
+ node.style.display = 'none';
103
+ }
104
+ return visible;
105
+ }
106
+
107
+ function toggleChildren(img, event) {
108
+ event.cancelBubble=true;
109
+ if (img.className.indexOf('empty') > -1)
110
+ return;
111
+
112
+ var minus = (img.className.indexOf('minus') > -1);
113
+
114
+ if (minus) {
115
+ img.className = 'toggle plus';
116
+ }
117
+ else
118
+ img.className = 'toggle minus';
119
+
120
+ var li = img.parentNode;
121
+ var ul = findUlChild(li);
122
+ if (ul) {
123
+ if (minus)
124
+ ul.style.display = 'none';
125
+ else
126
+ ul.style.display = 'block';
127
+ }
128
+ if (minus)
129
+ moveSelectionIfNecessary(li);
130
+ }
131
+
132
+ function showChildren(li) {
133
+ var img = li.firstChild;
134
+ if (img.className.indexOf('empty') > -1)
135
+ return;
136
+ img.className = 'toggle minus';
137
+
138
+ var ul = findUlChild(li);
139
+ if (ul) {
140
+ ul.style.display = 'block';
141
+ }
142
+ }
143
+
144
+ function setThreshold() {
145
+ var tv = document.getElementById("threshold").value;
146
+ if (tv.match(/[0-9]+([.,][0-9]+)?/)) {
147
+ var f = parseFloat(tv.replace(/,/, '.'));
148
+ var threads = document.getElementsByName("thread");
149
+ var l = threads.length;
150
+ for ( var i = 0; i < l ; i++ ) {
151
+ setThresholdUL(threads[i], f);
152
+ }
153
+ var p = selectedNode;
154
+ while (p && p.style.display=='none')
155
+ p=p.parentNode.parentNode;
156
+ if (p && p.nodeName=="LI")
157
+ selectNode(p);
158
+ }
159
+ else {
160
+ alert("Please specify a decimal number as threshold value!");
161
+ }
162
+ }
163
+
164
+ function expandAll(event) {
165
+ toggleAll(event, true);
166
+ }
167
+
168
+ function collapseAll(event) {
169
+ toggleAll(event, false);
170
+ selectNode(rootNode(), null);
171
+ }
172
+
173
+ function toggleAll(event, show) {
174
+ event.cancelBubble=true;
175
+ var threads = document.getElementsByName("thread");
176
+ var l = threads.length;
177
+ for ( var i = 0; i < l ; i++ ) {
178
+ showUL(threads[i], show);
179
+ }
180
+ }
181
+
182
+ function toggleHelp(node) {
183
+ var help = document.getElementById("help");
184
+ if (node.value == "Show Help") {
185
+ node.value = "Hide Help";
186
+ help.style.display = 'block';
187
+ }
188
+ else {
189
+ node.value = "Show Help";
190
+ help.style.display = 'none';
191
+ }
192
+ }
193
+
194
+ var selectedNode = null;
195
+ var selectedColor = null;
196
+ var selectedThread = null;
197
+
198
+ function descendentOf(a,b){
199
+ while (a!=b && b!=null)
200
+ b=b.parentNode;
201
+ return (a==b);
202
+ }
203
+
204
+ function moveSelectionIfNecessary(node){
205
+ if (descendentOf(node, selectedNode))
206
+ selectNode(node, null);
207
+ }
208
+
209
+ function selectNode(node, event) {
210
+ if (event) {
211
+ event.cancelBubble = true;
212
+ thread = findThread(node);
213
+ selectThread(thread);
214
+ }
215
+ if (selectedNode) {
216
+ selectedNode.style.background = selectedColor;
217
+ }
218
+ selectedNode = node;
219
+ selectedColor = node.style.background;
220
+ selectedNode.style.background = "red";
221
+ selectedNode.scrollIntoView();
222
+ window.scrollBy(0,-400);
223
+ }
224
+
225
+ function moveUp(){
226
+ move(selectedNode.previousSibling);
227
+ }
228
+
229
+ function moveDown(){
230
+ move(selectedNode.nextSibling);
231
+ }
232
+
233
+ function move(p) {
234
+ while (p && p.style.display == 'none')
235
+ p = p.nextSibling;
236
+ if (p && p.nodeName == "LI") {
237
+ selectNode(p, null);
238
+ }
239
+ }
240
+
241
+ function moveLeft(){
242
+ var p = selectedNode.parentNode.parentNode;
243
+ if (p && p.nodeName=="LI") {
244
+ selectNode(p, null);
245
+ }
246
+ }
247
+
248
+ function moveRight(){
249
+ if (!isLeafNode(selectedNode)) {
250
+ showChildren(selectedNode);
251
+ var ul = findUlChild(selectedNode);
252
+ if (ul) {
253
+ selectNode(ul.firstChild, null);
254
+ }
255
+ }
256
+ }
257
+
258
+ function moveForward(){
259
+ if (isLeafNode(selectedNode)) {
260
+ var p = selectedNode;
261
+ while ((p.nextSibling == null || p.nextSibling.style.display=='none') && p.nodeName=="LI") {
262
+ p = p.parentNode.parentNode;
263
+ }
264
+ if (p.nodeName=="LI")
265
+ selectNode(p.nextSibling, null);
266
+ }
267
+ else {
268
+ moveRight();
269
+ }
270
+ }
271
+
272
+ function isExpandedNode(li){
273
+ var img = li.firstChild;
274
+ return(img.className.indexOf('minus')>-1);
275
+ }
276
+
277
+ function moveBackward(){
278
+ var p = selectedNode;
279
+ var q = p.previousSibling;
280
+ while (q != null && q.style.display=='none')
281
+ q = q.previousSibling;
282
+ if (q == null) {
283
+ p = p.parentNode.parentNode;
284
+ } else {
285
+ while (!isLeafNode(q) && isExpandedNode(q)) {
286
+ q = findUlChild(q).lastChild;
287
+ while (q.style.display=='none')
288
+ q = q.previousSibling;
289
+ }
290
+ p = q;
291
+ }
292
+ if (p.nodeName=="LI")
293
+ selectNode(p, null);
294
+ }
295
+
296
+ function moveHome() {
297
+ selectNode(currentThread);
298
+ }
299
+
300
+ var currentThreadIndex = null;
301
+
302
+ function findThread(node){
303
+ while (node && !node.parentNode.nodeName.match(/BODY|DIV/g)) {
304
+ node = node.parentNode;
305
+ }
306
+ return node.firstChild;
307
+ }
308
+
309
+ function selectThread(node){
310
+ var threads = document.getElementsByName("thread");
311
+ currentThread = node;
312
+ for (var i=0; i<threads.length; i++) {
313
+ if (threads[i]==currentThread.parentNode)
314
+ currentThreadIndex = i;
315
+ }
316
+ }
317
+
318
+ function nextThread(){
319
+ var threads = document.getElementsByName("thread");
320
+ if (currentThreadIndex==threads.length-1)
321
+ currentThreadIndex = 0;
322
+ else
323
+ currentThreadIndex += 1
324
+ currentThread = threads[currentThreadIndex].firstChild;
325
+ selectNode(currentThread, null);
326
+ }
327
+
328
+ function previousThread(){
329
+ var threads = document.getElementsByName("thread");
330
+ if (currentThreadIndex==0)
331
+ currentThreadIndex = threads.length-1;
332
+ else
333
+ currentThreadIndex -= 1
334
+ currentThread = threads[currentThreadIndex].firstChild;
335
+ selectNode(currentThread, null);
336
+ }
337
+
338
+ function switchThread(node, event){
339
+ event.cancelBubble = true;
340
+ selectThread(node.nextSibling.firstChild);
341
+ selectNode(currentThread, null);
342
+ }
343
+
344
+ function handleKeyEvent(event){
345
+ var code = event.charCode ? event.charCode : event.keyCode;
346
+ var str = String.fromCharCode(code);
347
+ switch (str) {
348
+ case "a": moveLeft(); break;
349
+ case "s": moveDown(); break;
350
+ case "d": moveRight(); break;
351
+ case "w": moveUp(); break;
352
+ case "f": moveForward(); break;
353
+ case "b": moveBackward(); break;
354
+ case "x": toggleChildren(selectedNode.firstChild, event); break;
355
+ case "*": toggleLI(selectedNode); break;
356
+ case "n": nextThread(); break;
357
+ case "h": moveHome(); break;
358
+ case "p": previousThread(); break;
359
+ }
360
+ }
361
+ document.onkeypress=function(event){ handleKeyEvent(event) };
362
+
363
+ window.onload=function(){
364
+ var images = document.querySelectorAll(".toggle");
365
+ for (var i=0; i<images.length; i++) {
366
+ var img = images[i];
367
+ img.onclick = function(event){ toggleChildren(this, event); return false; };
368
+ }
369
+ var divs = document.getElementsByTagName("div");
370
+ for (i=0; i<divs.length; i++) {
371
+ var div = divs[i];
372
+ if (div.className == "thread")
373
+ div.onclick = function(event){ switchThread(this, event) };
374
+ }
375
+ var lis = document.getElementsByTagName("li");
376
+ for (var i=0; i<lis.length; i++) {
377
+ lis[i].onclick = function(event){ selectNode(this, event); };
378
+ }
379
+ var threads = document.getElementsByName("thread");;
380
+ currentThreadIndex = 0;
381
+ currentThread = threads[0].firstChild;
382
+ selectNode(currentThread, null);
383
+ };
384
+
385
+ </script>
@@ -0,0 +1,115 @@
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ class CallInfo
5
+ # part of this class is defined in C code.
6
+ # it provides the following attributes pertaining to tree structure:
7
+ # depth: tree level (0 == root)
8
+ # parent: parent call info (can be nil)
9
+ # children: array of call info children (can be empty)
10
+ # target: method info (containing an array of call infos)
11
+
12
+ def children_time
13
+ children.inject(0) do |sum, call_info|
14
+ sum += call_info.total_time
15
+ end
16
+ end
17
+
18
+ def stack
19
+ @stack ||= begin
20
+ methods = Array.new
21
+ call_info = self
22
+
23
+ while call_info
24
+ methods << call_info.target
25
+ call_info = call_info.parent
26
+ end
27
+ methods.reverse
28
+ end
29
+ end
30
+
31
+ def call_sequence
32
+ @call_sequence ||= begin
33
+ stack.map {|method| method.full_name}.join('->')
34
+ end
35
+ end
36
+
37
+ def root?
38
+ self.parent.nil?
39
+ end
40
+
41
+ def descendent_of(other)
42
+ p = self.parent
43
+ while p && p != other && p.depth > other.depth
44
+ p = p.parent
45
+ end
46
+ p == other
47
+ end
48
+
49
+ def self.roots_of(call_infos)
50
+ roots = []
51
+ sorted = call_infos.sort_by(&:depth).reverse
52
+ while call_info = sorted.shift
53
+ roots << call_info unless sorted.any?{|p| call_info.descendent_of(p)}
54
+ end
55
+ roots
56
+ end
57
+
58
+ def to_s
59
+ "#{target.full_name} (c: #{called}, tt: #{total_time}, st: #{self_time}, ct: #{children_time})"
60
+ end
61
+
62
+ def inspect
63
+ super + "(#{target.full_name}, d: #{depth}, c: #{called}, tt: #{total_time}, st: #{self_time}, ct: #{children_time})"
64
+ end
65
+
66
+ # eliminate call info from the call tree.
67
+ # adds self and wait time to parent and attaches called methods to parent.
68
+ # merges call trees for methods called from both praent end self.
69
+ def eliminate!
70
+ # puts "eliminating #{self}"
71
+ return unless parent
72
+ parent.add_self_time(self)
73
+ parent.add_wait_time(self)
74
+ children.each do |kid|
75
+ if call = parent.find_call(kid)
76
+ call.merge_call_tree(kid)
77
+ else
78
+ parent.children << kid
79
+ # $stderr.puts "setting parent of #{kid}\nto #{parent}"
80
+ kid.parent = parent
81
+ end
82
+ end
83
+ parent.children.delete(self)
84
+ end
85
+
86
+ # find a specific call in list of children. returns nil if not found.
87
+ # note: there can't be more than one child with a given target method. in other words:
88
+ # x.children.grep{|y|y.target==m}.size <= 1 for all method infos m and call infos x
89
+ def find_call(other)
90
+ matching = children.select { |kid| kid.target == other.target }
91
+ raise "inconsistent call tree" unless matching.size <= 1
92
+ matching.first
93
+ end
94
+
95
+ # merge two call trees. adds self, wait, and total time of other to self and merges children of other into children of self.
96
+ def merge_call_tree(other)
97
+ # $stderr.puts "merging #{self}\nand #{other}"
98
+ self.called += other.called
99
+ add_self_time(other)
100
+ add_wait_time(other)
101
+ add_total_time(other)
102
+ other.children.each do |other_kid|
103
+ if kid = find_call(other_kid)
104
+ # $stderr.puts "merging kids"
105
+ kid.merge_call_tree(other_kid)
106
+ else
107
+ other_kid.parent = self
108
+ children << other_kid
109
+ end
110
+ end
111
+ other.children.clear
112
+ other.target.call_infos.delete(other)
113
+ end
114
+ end
115
+ end