ruby-prof 0.18.0-x64-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,70 @@
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ # Generates flat[link:files/examples/flat_txt.html] profile reports as text.
5
+ # To use the flat printer:
6
+ #
7
+ # result = RubyProf.profile do
8
+ # [code to profile]
9
+ # end
10
+ #
11
+ # printer = RubyProf::FlatPrinter.new(result)
12
+ # printer.print(STDOUT, {})
13
+ #
14
+ class FlatPrinter < AbstractPrinter
15
+ # Override for this printer to sort by self time by default
16
+ def sort_method
17
+ @options[:sort_method] || :self_time
18
+ end
19
+
20
+ private
21
+
22
+ #def print_threads
23
+ # @result.threads.each do |thread|
24
+ # print_thread(thread)
25
+ # @output << "\n" * 2
26
+ # end
27
+ #end
28
+
29
+ def print_header(thread)
30
+ @output << "Measure Mode: %s\n" % RubyProf.measure_mode_string
31
+ @output << "Thread ID: %d\n" % thread.id
32
+ @output << "Fiber ID: %d\n" % thread.fiber_id unless thread.id == thread.fiber_id
33
+ @output << "Total: %0.6f\n" % thread.total_time
34
+ @output << "Sort by: #{sort_method}\n"
35
+ @output << "\n"
36
+ @output << " %self total self wait child calls name\n"
37
+ end
38
+
39
+ def print_methods(thread)
40
+ total_time = thread.total_time
41
+ methods = thread.methods.sort_by(&sort_method).reverse
42
+
43
+ sum = 0
44
+ methods.each do |method|
45
+ self_percent = (method.self_time / total_time) * 100
46
+ next if self_percent < min_percent
47
+
48
+ sum += method.self_time
49
+ #self_time_called = method.called > 0 ? method.self_time/method.called : 0
50
+ #total_time_called = method.called > 0? method.total_time/method.called : 0
51
+
52
+ @output << "%6.2f %9.3f %9.3f %9.3f %9.3f %8d %s%s\n" % [
53
+ method.self_time / total_time * 100, # %self
54
+ method.total_time, # total
55
+ method.self_time, # self
56
+ method.wait_time, # wait
57
+ method.children_time, # children
58
+ method.called, # calls
59
+ method.recursive? ? "*" : " ", # cycle
60
+ method_name(method) # name
61
+ ]
62
+ end
63
+ end
64
+
65
+ def print_footer(thread)
66
+ @output << "\n"
67
+ @output << "* indicates recursively called methods\n"
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ # Generates flat[link:files/examples/flat_txt.html] profile reports as text.
5
+ # To use the flat printer with line numbers:
6
+ #
7
+ # result = RubyProf.profile do
8
+ # [code to profile]
9
+ # end
10
+ #
11
+ # printer = RubyProf::FlatPrinterWithLineNumbers.new(result)
12
+ # printer.print(STDOUT, {})
13
+ #
14
+ class FlatPrinterWithLineNumbers < FlatPrinter
15
+ def print_methods(thread)
16
+ @editor = editor_uri
17
+ total_time = thread.total_time
18
+
19
+ methods = thread.methods.sort_by(&sort_method).reverse
20
+ sum = 0
21
+ methods.each do |method|
22
+ self_percent = (method.self_time / total_time) * 100
23
+ next if self_percent < min_percent
24
+
25
+ sum += method.self_time
26
+ #self_time_called = method.called > 0 ? method.self_time/method.called : 0
27
+ #total_time_called = method.called > 0? method.total_time/method.called : 0
28
+
29
+ @output << "%6.2f %9.3f %9.3f %9.3f %9.3f %8d %s%s" % [
30
+ method.self_time / total_time * 100, # %self
31
+ method.total_time, # total
32
+ method.self_time, # self
33
+ method.wait_time, # wait
34
+ method.children_time, # children
35
+ method.called, # calls
36
+ method.recursive? ? "*" : " ", # cycle
37
+ method_name(method) # name
38
+ ]
39
+ if method.source_file == 'ruby_runtime'
40
+ @output << "\n"
41
+ else
42
+ @output << "\n defined at:\n"
43
+ @output << defined_at_format % [File.expand_path(method.source_file), method.line]
44
+ end
45
+
46
+ callers = []
47
+ method.call_infos.each do |ci|
48
+ if ci.parent && ci.parent.target.source_file != 'ruby_runtime'
49
+ callers << [method_name(ci.parent.target), File.expand_path(ci.parent.target.source_file), ci.parent.target.line]
50
+ end
51
+ end
52
+ # make sure callers are unique
53
+ callers.uniq!
54
+
55
+ unless callers.empty?
56
+ @output << " called from:\n"
57
+ callers.each do |args|
58
+ @output << called_from_format % args
59
+ end
60
+ end
61
+ @output << "\n"
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def defined_at_format
68
+ if @editor
69
+ " #{@editor}://open?url=file://%s&line=%s\n"
70
+ else
71
+ " %s:%s\n"
72
+ end
73
+ end
74
+
75
+ def called_from_format
76
+ if @editor
77
+ " %s (#{@editor}://open?url=file://%s&line=%s)\n"
78
+ else
79
+ " %s (%s:%s)\n"
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,249 @@
1
+ # encoding: utf-8
2
+
3
+ require 'erb'
4
+
5
+ module RubyProf
6
+ # Generates graph[link:files/examples/graph_html.html] profile reports as html.
7
+ # To use the graph html printer:
8
+ #
9
+ # result = RubyProf.profile do
10
+ # [code to profile]
11
+ # end
12
+ #
13
+ # printer = RubyProf::GraphHtmlPrinter.new(result)
14
+ # printer.print(STDOUT, :min_percent=>0)
15
+ #
16
+ # The Graph printer takes the following options in its print methods:
17
+ # :filename - specify a file to use that contains the ERB
18
+ # template to use, instead of the built-in self.template
19
+ #
20
+ # :template - specify an ERB template to use, instead of the
21
+ # built-in self.template
22
+ #
23
+ # :editor_uri - Specifies editor uri scheme used for opening files
24
+ # e.g. :atm or :mvim. For OS X default is :txmt.
25
+ # Use RUBY_PROF_EDITOR_URI environment variable to overide.
26
+
27
+ class GraphHtmlPrinter < AbstractPrinter
28
+ include ERB::Util
29
+
30
+ def setup_options(options)
31
+ super(options)
32
+
33
+ filename = options[:filename]
34
+ template = filename ? File.read(filename).untaint : (options[:template] || self.template)
35
+ @erb = ERB.new(template)
36
+ @erb.filename = filename
37
+ end
38
+
39
+ def print(output = STDOUT, options = {})
40
+ @output = output
41
+ setup_options(options)
42
+ @editor = editor_uri
43
+ @output << @erb.result(binding).split("\n").map(&:rstrip).join("\n") << "\n"
44
+ end
45
+
46
+ # Creates a link to a method. Note that we do not create
47
+ # links to methods which are under the min_perecent
48
+ # specified by the user, since they will not be
49
+ # printed out.
50
+ def create_link(thread, overall_time, method)
51
+ total_percent = (method.total_time/overall_time) * 100
52
+ if total_percent < min_percent
53
+ # Just return name
54
+ h method.full_name
55
+ else
56
+ href = '#' + method_href(thread, method)
57
+ "<a href=\"#{href}\">#{h method.full_name}</a>"
58
+ end
59
+ end
60
+
61
+ def method_href(thread, method)
62
+ h(method.full_name.gsub(/[><#\.\?=:]/,"_") + "_" + thread.fiber_id.to_s)
63
+ end
64
+
65
+ def file_link(path, linenum)
66
+ srcfile = File.expand_path(path)
67
+ if srcfile =~ /\/ruby_runtime$/
68
+ ""
69
+ else
70
+ if @editor
71
+ "<a href=\"#{@editor}://" \
72
+ "open?url=file://#{h srcfile}&line=#{linenum}\"" \
73
+ "title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
74
+ else
75
+ "<a href=\"file://#{h srcfile}##{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
76
+ end
77
+ end
78
+ end
79
+
80
+ def template
81
+ '
82
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
83
+ <html>
84
+ <head>
85
+ <style media="all" type="text/css">
86
+ table {
87
+ border-collapse: collapse;
88
+ border: 1px solid #CCC;
89
+ font-family: Verdana, Arial, Helvetica, sans-serif;
90
+ font-size: 9pt;
91
+ line-height: normal;
92
+ width: 100%;
93
+ }
94
+
95
+ th {
96
+ text-align: center;
97
+ border-top: 1px solid #FB7A31;
98
+ border-bottom: 1px solid #FB7A31;
99
+ background: #FFC;
100
+ padding: 0.3em;
101
+ border-left: 1px solid silver;
102
+ }
103
+
104
+ tr.break td {
105
+ border: 0;
106
+ border-top: 1px solid #FB7A31;
107
+ padding: 0;
108
+ margin: 0;
109
+ }
110
+
111
+ tr.method td {
112
+ font-weight: bold;
113
+ }
114
+
115
+ td {
116
+ padding: 0.3em;
117
+ }
118
+
119
+ td:first-child {
120
+ width: 190px;
121
+ }
122
+
123
+ td {
124
+ border-left: 1px solid #CCC;
125
+ text-align: center;
126
+ }
127
+
128
+ .method_name {
129
+ text-align: left;
130
+ }
131
+
132
+ tfoot td {
133
+ text-align: left;
134
+ }
135
+ </style>
136
+ </head>
137
+ <body>
138
+ <h1>Profile Report: <%= RubyProf.measure_mode_string %></h1>
139
+ <!-- Threads Table -->
140
+ <table>
141
+ <tr>
142
+ <th>Thread ID</th>
143
+ <th>Fiber ID</th>
144
+ <th>Total Time</th>
145
+ </tr>
146
+ <% for thread in @result.threads %>
147
+ <tr>
148
+ <td><%= thread.id %></td>
149
+ <td><a href="#<%= thread.fiber_id %>"><%= thread.fiber_id %></a></td>
150
+ <td><%= thread.total_time %></td>
151
+ </tr>
152
+ <% end %>
153
+ </table>
154
+ <!-- Methods Tables -->
155
+ <%
156
+ for thread in @result.threads
157
+ methods = thread.methods
158
+ total_time = thread.total_time
159
+ %>
160
+ <h2><a name="<%= thread.fiber_id %>">Thread <%= thread.id %>, Fiber: <%= thread.fiber_id %></a></h2>
161
+ <table>
162
+ <thead>
163
+ <tr>
164
+ <th>%Total</th>
165
+ <th>%Self</th>
166
+ <th>Total</th>
167
+ <th>Self</th>
168
+ <th>Wait</th>
169
+ <th>Child</th>
170
+ <th>Calls</th>
171
+ <th class="method_name">Name</th>
172
+ <th>Line</th>
173
+ </tr>
174
+ </thead>
175
+ <tbody>
176
+ <%
177
+ min_time = @options[:min_time] || (@options[:nonzero] ? 0.005 : nil)
178
+ methods.sort_by(&sort_method).reverse_each do |method|
179
+ total_percentage = (method.total_time/total_time) * 100
180
+ next if total_percentage < min_percent
181
+ next if min_time && method.total_time < min_time
182
+ self_percentage = (method.self_time/total_time) * 100
183
+ %>
184
+ <!-- Parents -->
185
+ <%
186
+ for caller in method.aggregate_parents.sort_by(&:total_time)
187
+ next unless caller.parent
188
+ next if min_time && caller.total_time < min_time
189
+ %>
190
+ <tr>
191
+ <td>&nbsp;</td>
192
+ <td>&nbsp;</td>
193
+ <td><%= sprintf("%.2f", caller.total_time) %></td>
194
+ <td><%= sprintf("%.2f", caller.self_time) %></td>
195
+ <td><%= sprintf("%.2f", caller.wait_time) %></td>
196
+ <td><%= sprintf("%.2f", caller.children_time) %></td>
197
+ <td><%= "#{caller.called}/#{method.called}" %></td>
198
+ <td class="method_name"><%= create_link(thread, total_time, caller.parent.target) %></td>
199
+ <td><%= file_link(caller.parent.target.source_file, caller.line) %></td>
200
+ </tr>
201
+ <% end %>
202
+ <tr class="method">
203
+ <td><%= sprintf("%.2f%%", total_percentage) %></td>
204
+ <td><%= sprintf("%.2f%%", self_percentage) %></td>
205
+ <td><%= sprintf("%.2f", method.total_time) %></td>
206
+ <td><%= sprintf("%.2f", method.self_time) %></td>
207
+ <td><%= sprintf("%.2f", method.wait_time) %></td>
208
+ <td><%= sprintf("%.2f", method.children_time) %></td>
209
+ <td><%= sprintf("%i", method.called) %></td>
210
+ <td class="method_name">
211
+ <a name="<%= method_href(thread, method) %>">
212
+ <%= method.recursive? ? "*" : " "%><%= h method.full_name %>
213
+ </a>
214
+ </td>
215
+ <td><%= file_link(method.source_file, method.line) %></td>
216
+ </tr>
217
+ <!-- Children -->
218
+ <%
219
+ for callee in method.aggregate_children.sort_by(&:total_time).reverse
220
+ next if min_time && callee.total_time < min_time
221
+ %>
222
+ <tr>
223
+ <td>&nbsp;</td>
224
+ <td>&nbsp;</td>
225
+ <td><%= sprintf("%.2f", callee.total_time) %></td>
226
+ <td><%= sprintf("%.2f", callee.self_time) %></td>
227
+ <td><%= sprintf("%.2f", callee.wait_time) %></td>
228
+ <td><%= sprintf("%.2f", callee.children_time) %></td>
229
+ <td><%= "#{callee.called}/#{callee.target.called}" %></td>
230
+ <td class="method_name"><%= create_link(thread, total_time, callee.target) %></td>
231
+ <td><%= file_link(method.source_file, callee.line) %></td>
232
+ </tr>
233
+ <% end %>
234
+ <!-- Create divider row -->
235
+ <tr class="break"><td colspan="9"></td></tr>
236
+ <% end %>
237
+ </tbody>
238
+ <tfoot>
239
+ <tr>
240
+ <td colspan="9">* indicates recursively called methods</td>
241
+ </tr>
242
+ </tfoot>
243
+ </table>
244
+ <% end %>
245
+ </body>
246
+ </html>'
247
+ end
248
+ end
249
+ end
@@ -0,0 +1,116 @@
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ # Generates graph[link:files/examples/graph_txt.html] profile reports as text.
5
+ # To use the graph printer:
6
+ #
7
+ # result = RubyProf.profile do
8
+ # [code to profile]
9
+ # end
10
+ #
11
+ # printer = RubyProf::GraphPrinter.new(result)
12
+ # printer.print(STDOUT, {})
13
+ #
14
+ # The constructor takes two arguments. See the README
15
+
16
+ class GraphPrinter < AbstractPrinter
17
+ PERCENTAGE_WIDTH = 8
18
+ TIME_WIDTH = 11
19
+ CALL_WIDTH = 17
20
+
21
+ private
22
+
23
+ def print_header(thread)
24
+ @output << "Measure Mode: %s\n" % RubyProf.measure_mode_string
25
+ @output << "Thread ID: #{thread.id}\n"
26
+ @output << "Fiber ID: #{thread.fiber_id}\n" unless thread.id == thread.fiber_id
27
+ @output << "Total Time: #{thread.total_time}\n"
28
+ @output << "Sort by: #{sort_method}\n"
29
+ @output << "\n"
30
+
31
+ # 1 is for % sign
32
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
33
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
34
+ @output << sprintf("%#{TIME_WIDTH}s", "total")
35
+ @output << sprintf("%#{TIME_WIDTH}s", "self")
36
+ @output << sprintf("%#{TIME_WIDTH}s", "wait")
37
+ @output << sprintf("%#{TIME_WIDTH}s", "child")
38
+ @output << sprintf("%#{CALL_WIDTH}s", "calls")
39
+ @output << " name"
40
+ @output << "\n"
41
+ end
42
+
43
+ def print_methods(thread)
44
+ total_time = thread.total_time
45
+ # Sort methods from longest to shortest total time
46
+ methods = thread.methods.sort_by(&sort_method)
47
+
48
+ # Print each method in total time order
49
+ methods.reverse_each do |method|
50
+ total_percentage = (method.total_time/total_time) * 100
51
+ next if total_percentage < min_percent
52
+
53
+ self_percentage = (method.self_time/total_time) * 100
54
+
55
+ @output << "-" * 80 << "\n"
56
+ print_parents(thread, method)
57
+
58
+ # 1 is for % sign
59
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", total_percentage)
60
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", self_percentage)
61
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.total_time)
62
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.self_time)
63
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.wait_time)
64
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.children_time)
65
+ @output << sprintf("%#{CALL_WIDTH}i", method.called)
66
+ @output << sprintf(" %s", method.recursive? ? "*" : " ")
67
+ @output << sprintf("%s", method_name(method))
68
+ if print_file
69
+ @output << sprintf(" %s:%s", method.source_file, method.line)
70
+ end
71
+ @output << "\n"
72
+
73
+ print_children(method)
74
+ end
75
+ end
76
+
77
+ def print_parents(thread, method)
78
+ method.aggregate_parents.sort_by(&:total_time).each do |caller|
79
+ next unless caller.parent
80
+ @output << " " * 2 * PERCENTAGE_WIDTH
81
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.total_time)
82
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.self_time)
83
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.wait_time)
84
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.children_time)
85
+
86
+ call_called = "#{caller.called}/#{method.called}"
87
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
88
+ @output << sprintf(" %s", caller.parent.target.full_name)
89
+ @output << "\n"
90
+ end
91
+ end
92
+
93
+ def print_children(method)
94
+ method.aggregate_children.sort_by(&:total_time).reverse.each do |child|
95
+ # Get children method
96
+
97
+ @output << " " * 2 * PERCENTAGE_WIDTH
98
+
99
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.total_time)
100
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.self_time)
101
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.wait_time)
102
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.children_time)
103
+
104
+ call_called = "#{child.called}/#{child.target.called}"
105
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
106
+ @output << sprintf(" %s", child.target.full_name)
107
+ @output << "\n"
108
+ end
109
+ end
110
+
111
+ def print_footer(thread)
112
+ @output << "\n"
113
+ @output << "* indicates recursively called methods\n"
114
+ end
115
+ end
116
+ end