ruby-prof 0.8.1-x86-mswin32

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 (64) hide show
  1. data/CHANGES +221 -0
  2. data/LICENSE +23 -0
  3. data/README +432 -0
  4. data/Rakefile +159 -0
  5. data/bin/ruby-prof +224 -0
  6. data/examples/flat.txt +55 -0
  7. data/examples/graph.html +823 -0
  8. data/examples/graph.txt +170 -0
  9. data/ext/ruby_prof/measure_allocations.h +58 -0
  10. data/ext/ruby_prof/measure_cpu_time.h +152 -0
  11. data/ext/ruby_prof/measure_gc_runs.h +76 -0
  12. data/ext/ruby_prof/measure_gc_time.h +57 -0
  13. data/ext/ruby_prof/measure_memory.h +101 -0
  14. data/ext/ruby_prof/measure_process_time.h +52 -0
  15. data/ext/ruby_prof/measure_wall_time.h +53 -0
  16. data/ext/ruby_prof/mingw/Rakefile +23 -0
  17. data/ext/ruby_prof/mingw/build.rake +38 -0
  18. data/ext/ruby_prof/ruby_prof.c +1747 -0
  19. data/ext/ruby_prof/ruby_prof.h +188 -0
  20. data/ext/ruby_prof/version.h +4 -0
  21. data/lib/1.8/ruby_prof.so +0 -0
  22. data/lib/1.9/ruby_prof.so +0 -0
  23. data/lib/ruby-prof.rb +56 -0
  24. data/lib/ruby-prof/abstract_printer.rb +41 -0
  25. data/lib/ruby-prof/aggregate_call_info.rb +62 -0
  26. data/lib/ruby-prof/call_info.rb +47 -0
  27. data/lib/ruby-prof/call_tree_printer.rb +84 -0
  28. data/lib/ruby-prof/flat_printer.rb +78 -0
  29. data/lib/ruby-prof/flat_printer_with_line_numbers.rb +72 -0
  30. data/lib/ruby-prof/graph_html_printer.rb +256 -0
  31. data/lib/ruby-prof/graph_printer.rb +157 -0
  32. data/lib/ruby-prof/method_info.rb +111 -0
  33. data/lib/ruby-prof/symbol_to_proc.rb +8 -0
  34. data/lib/ruby-prof/task.rb +146 -0
  35. data/lib/ruby-prof/test.rb +148 -0
  36. data/lib/unprof.rb +8 -0
  37. data/rails/environment/profile.rb +24 -0
  38. data/rails/example/example_test.rb +9 -0
  39. data/rails/profile_test_helper.rb +21 -0
  40. data/test/aggregate_test.rb +121 -0
  41. data/test/basic_test.rb +290 -0
  42. data/test/current_failures_windows +8 -0
  43. data/test/do_nothing.rb +0 -0
  44. data/test/duplicate_names_test.rb +32 -0
  45. data/test/enumerable_test.rb +16 -0
  46. data/test/exceptions_test.rb +15 -0
  47. data/test/exclude_threads_test.rb +54 -0
  48. data/test/exec_test.rb +14 -0
  49. data/test/line_number_test.rb +73 -0
  50. data/test/measurement_test.rb +121 -0
  51. data/test/module_test.rb +54 -0
  52. data/test/no_method_class_test.rb +13 -0
  53. data/test/prime.rb +58 -0
  54. data/test/prime_test.rb +13 -0
  55. data/test/printers_test.rb +130 -0
  56. data/test/recursive_test.rb +275 -0
  57. data/test/ruby-prof-bin +20 -0
  58. data/test/singleton_test.rb +37 -0
  59. data/test/stack_test.rb +138 -0
  60. data/test/start_stop_test.rb +95 -0
  61. data/test/test_suite.rb +23 -0
  62. data/test/thread_test.rb +173 -0
  63. data/test/unique_call_path_test.rb +225 -0
  64. metadata +143 -0
@@ -0,0 +1,78 @@
1
+ require 'ruby-prof/abstract_printer'
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, 0)
13
+ #
14
+ class FlatPrinter < AbstractPrinter
15
+ # Print a flat profile report to the provided output.
16
+ #
17
+ # output - Any IO oject, including STDOUT or a file.
18
+ # The default value is STDOUT.
19
+ #
20
+ # options - Hash of print options. See #setup_options
21
+ # for more information.
22
+ #
23
+ def print(output = STDOUT, options = {})
24
+ @output = output
25
+ setup_options(options)
26
+ print_threads
27
+ end
28
+
29
+ private
30
+
31
+ def print_threads
32
+ @result.threads.each do |thread_id, methods|
33
+ print_methods(thread_id, methods)
34
+ @output << "\n" * 2
35
+ end
36
+ end
37
+
38
+ def print_methods(thread_id, methods)
39
+ # Get total time
40
+ toplevel = methods.max
41
+ total_time = toplevel.total_time
42
+ if total_time == 0
43
+ total_time = 0.01
44
+ end
45
+
46
+ # Now sort methods by largest self time,
47
+ # not total time like in other printouts
48
+ methods = methods.sort do |m1, m2|
49
+ m1.self_time <=> m2.self_time
50
+ end.reverse
51
+
52
+ @output << "Thread ID: %d\n" % thread_id
53
+ @output << "Total: %0.6f\n" % total_time
54
+ @output << "\n"
55
+ @output << " %self total self wait child calls name\n"
56
+
57
+ sum = 0
58
+ methods.each do |method|
59
+ self_percent = (method.self_time / total_time) * 100
60
+ next if self_percent < min_percent
61
+
62
+ sum += method.self_time
63
+ #self_time_called = method.called > 0 ? method.self_time/method.called : 0
64
+ #total_time_called = method.called > 0? method.total_time/method.called : 0
65
+
66
+ @output << "%6.2f %8.2f %8.2f %8.2f %8.2f %8d %s\n" % [
67
+ method.self_time / total_time * 100, # %self
68
+ method.total_time, # total
69
+ method.self_time, # self
70
+ method.wait_time, # wait
71
+ method.children_time, # children
72
+ method.called, # calls
73
+ method_name(method) # name
74
+ ]
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,72 @@
1
+ require 'ruby-prof/abstract_printer'
2
+ require 'pathname'
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, 0)
13
+ #
14
+ class FlatPrinterWithLineNumbers < FlatPrinter
15
+
16
+ def print_methods(thread_id, methods)
17
+ # Get total time
18
+ toplevel = methods.max
19
+ total_time = toplevel.total_time
20
+ if total_time == 0
21
+ total_time = 0.01
22
+ end
23
+
24
+ # Now sort methods by largest self time,
25
+ # not total time like in other printouts
26
+ methods = methods.sort do |m1, m2|
27
+ m1.self_time <=> m2.self_time
28
+ end.reverse
29
+
30
+ @output << "Thread ID: %d\n" % thread_id
31
+ @output << "Total: %0.6f\n" % total_time
32
+ @output << "\n"
33
+ @output << " %self total self wait child calls name\n"
34
+ sum = 0
35
+ methods.each do |method|
36
+ self_percent = (method.self_time / total_time) * 100
37
+ next if self_percent < min_percent
38
+
39
+ sum += method.self_time
40
+ #self_time_called = method.called > 0 ? method.self_time/method.called : 0
41
+ #total_time_called = method.called > 0? method.total_time/method.called : 0
42
+
43
+ @output << "%6.2f %8.2f %8.2f %8.2f %8.2f %8d %s " % [
44
+ method.self_time / total_time * 100, # %self
45
+ method.total_time, # total
46
+ method.self_time, # self
47
+ method.wait_time, # wait
48
+ method.children_time, # children
49
+ method.called, # calls
50
+ method_name(method), # name
51
+ ]
52
+ if method.source_file != 'ruby_runtime'
53
+ @output << " %s:%s" % [File.expand_path(method.source_file), method.line]
54
+ end
55
+ @output << "\n\tcalled from: "
56
+
57
+ # make sure they're unique
58
+ method.call_infos.map{|ci|
59
+ if ci.parent && ci.parent.target.source_file != 'ruby_runtime'
60
+ [method_name(ci.parent.target), File.expand_path(ci.parent.target.source_file), ci.parent.target.line]
61
+ else
62
+ nil
63
+ end
64
+ }.compact.uniq.each{|args|
65
+ @output << " %s (%s:%s) " % args
66
+ }
67
+ @output << "\n\n"
68
+ end
69
+ end
70
+ end
71
+ end
72
+
@@ -0,0 +1,256 @@
1
+ require 'ruby-prof/abstract_printer'
2
+ require 'erb'
3
+
4
+ module RubyProf
5
+ # Generates graph[link:files/examples/graph_html.html] profile reports as html.
6
+ # To use the grap html printer:
7
+ #
8
+ # result = RubyProf.profile do
9
+ # [code to profile]
10
+ # end
11
+ #
12
+ # printer = RubyProf::GraphHtmlPrinter.new(result)
13
+ # printer.print(STDOUT, :min_percent=>0)
14
+ #
15
+ # The constructor takes two arguments. The first is
16
+ # a RubyProf::Result object generated from a profiling
17
+ # run. The second is the minimum %total (the methods
18
+ # total time divided by the overall total time) that
19
+ # a method must take for it to be printed out in
20
+ # the report. Use this parameter to eliminate methods
21
+ # that are not important to the overall profiling results.
22
+
23
+ class GraphHtmlPrinter < AbstractPrinter
24
+ include ERB::Util
25
+
26
+ PERCENTAGE_WIDTH = 8
27
+ TIME_WIDTH = 10
28
+ CALL_WIDTH = 20
29
+
30
+ # Create a GraphPrinter. Result is a RubyProf::Result
31
+ # object generated from a profiling run.
32
+ def initialize(result)
33
+ super(result)
34
+ @thread_times = Hash.new
35
+ calculate_thread_times
36
+ end
37
+
38
+ # Print a graph html report to the provided output.
39
+ #
40
+ # output - Any IO oject, including STDOUT or a file.
41
+ # The default value is STDOUT.
42
+ #
43
+ # options - Hash of print options. See #setup_options
44
+ # for more information.
45
+ #
46
+ def print(output = STDOUT, options = {})
47
+ @output = output
48
+ setup_options(options)
49
+
50
+ filename = options[:filename]
51
+ template = filename ? File.read(filename).untaint : (options[:template] || self.template)
52
+ _erbout = @output
53
+ erb = ERB.new(template, nil, nil)
54
+ erb.filename = filename
55
+ @output << erb.result(binding)
56
+ end
57
+
58
+ # These methods should be private but then ERB doesn't
59
+ # work. Turn off RDOC though
60
+ #--
61
+ def calculate_thread_times
62
+ # Cache thread times since this is an expensive
63
+ # operation with the required sorting
64
+ @result.threads.each do |thread_id, methods|
65
+ top = methods.max
66
+
67
+ thread_time = 0.01
68
+ thread_time = top.total_time if top.total_time > 0
69
+
70
+ @thread_times[thread_id] = thread_time
71
+ end
72
+ end
73
+
74
+ def thread_time(thread_id)
75
+ @thread_times[thread_id]
76
+ end
77
+
78
+ def total_percent(thread_id, method)
79
+ overall_time = self.thread_time(thread_id)
80
+ (method.total_time/overall_time) * 100
81
+ end
82
+
83
+ def self_percent(method)
84
+ overall_time = self.thread_time(method.thread_id)
85
+ (method.self_time/overall_time) * 100
86
+ end
87
+
88
+ # Creates a link to a method. Note that we do not create
89
+ # links to methods which are under the min_perecent
90
+ # specified by the user, since they will not be
91
+ # printed out.
92
+ def create_link(thread_id, method)
93
+ if self.total_percent(thread_id, method) < min_percent
94
+ # Just return name
95
+ h method.full_name
96
+ else
97
+ href = '#' + method_href(thread_id, method)
98
+ "<a href=\"#{href}\">#{h method.full_name}</a>"
99
+ end
100
+ end
101
+
102
+ def method_href(thread_id, method)
103
+ h(method.full_name.gsub(/[><#\.\?=:]/,"_") + "_" + thread_id.to_s)
104
+ end
105
+
106
+ def template
107
+ '
108
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
109
+ <html>
110
+ <head>
111
+ <style media="all" type="text/css">
112
+ table {
113
+ border-collapse: collapse;
114
+ border: 1px solid #CCC;
115
+ font-family: Verdana, Arial, Helvetica, sans-serif;
116
+ font-size: 9pt;
117
+ line-height: normal;
118
+ width: 100%;
119
+ }
120
+
121
+ th {
122
+ text-align: center;
123
+ border-top: 1px solid #FB7A31;
124
+ border-bottom: 1px solid #FB7A31;
125
+ background: #FFC;
126
+ padding: 0.3em;
127
+ border-left: 1px solid silver;
128
+ }
129
+
130
+ tr.break td {
131
+ border: 0;
132
+ border-top: 1px solid #FB7A31;
133
+ padding: 0;
134
+ margin: 0;
135
+ }
136
+
137
+ tr.method td {
138
+ font-weight: bold;
139
+ }
140
+
141
+ td {
142
+ padding: 0.3em;
143
+ }
144
+
145
+ td:first-child {
146
+ width: 190px;
147
+ }
148
+
149
+ td {
150
+ border-left: 1px solid #CCC;
151
+ text-align: center;
152
+ }
153
+
154
+ .method_name {
155
+ text-align: left;
156
+ }
157
+ </style>
158
+ </head>
159
+ <body>
160
+ <h1>Profile Report</h1>
161
+ <!-- Threads Table -->
162
+ <table>
163
+ <tr>
164
+ <th>Thread ID</th>
165
+ <th>Total Time</th>
166
+ </tr>
167
+ <% for thread_id, methods in @result.threads %>
168
+ <tr>
169
+ <td><a href="#<%= thread_id %>"><%= thread_id %></a></td>
170
+ <td><%= thread_time(thread_id) %></td>
171
+ </tr>
172
+ <% end %>
173
+ </table>
174
+
175
+ <!-- Methods Tables -->
176
+ <% for thread_id, methods in @result.threads
177
+ total_time = thread_time(thread_id) %>
178
+ <h2><a name="<%= thread_id %>">Thread <%= thread_id %></a></h2>
179
+
180
+ <table>
181
+ <tr>
182
+ <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Total") %></th>
183
+ <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Self") %></th>
184
+ <th><%= sprintf("%#{TIME_WIDTH}s", "Total") %></th>
185
+ <th><%= sprintf("%#{TIME_WIDTH}s", "Self") %></th>
186
+ <th><%= sprintf("%#{TIME_WIDTH}s", "Wait") %></th>
187
+ <th><%= sprintf("%#{TIME_WIDTH+2}s", "Child") %></th>
188
+ <th><%= sprintf("%#{CALL_WIDTH}s", "Calls") %></th>
189
+ <th class="method_name">Name</th>
190
+ <th>Line</th>
191
+ </tr>
192
+
193
+ <% min_time = @options[:min_time] || (@options[:nonzero] ? 0.005 : nil)
194
+ methods.sort.reverse_each do |method|
195
+ total_percentage = (method.total_time/total_time) * 100
196
+ next if total_percentage < min_percent
197
+ next if min_time && method.total_time < min_time
198
+ self_percentage = (method.self_time/total_time) * 100 %>
199
+
200
+ <!-- Parents -->
201
+ <% for caller in method.aggregate_parents.sort_by(&:total_time)
202
+ next unless caller.parent
203
+ next if min_time && caller.total_time < min_time %>
204
+ <tr>
205
+ <td>&nbsp;</td>
206
+ <td>&nbsp;</td>
207
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.total_time) %></td>
208
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.self_time) %></td>
209
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.wait_time) %></td>
210
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.children_time) %></td>
211
+ <% called = "#{caller.called}/#{method.called}" %>
212
+ <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
213
+ <td class="method_name"><%= create_link(thread_id, caller.parent.target) %></td>
214
+ <td><a href="file://<%=h srcfile=File.expand_path(caller.parent.target.source_file) %>#line=<%= linenum=caller.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= caller.line %></a></td>
215
+ </tr>
216
+ <% end %>
217
+
218
+ <tr class="method">
219
+ <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage) %></td>
220
+ <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage) %></td>
221
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", method.total_time) %></td>
222
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", method.self_time) %></td>
223
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", method.wait_time) %></td>
224
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", method.children_time) %></td>
225
+ <td><%= sprintf("%#{CALL_WIDTH}i", method.called) %></td>
226
+ <td class="method_name"><a name="<%= method_href(thread_id, method) %>"><%= h method.full_name %></a></td>
227
+ <td><a href="file://<%=h srcfile=File.expand_path(method.source_file) %>#line=<%= linenum=method.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= method.line %></a></td>
228
+ </tr>
229
+
230
+ <!-- Children -->
231
+ <% for callee in method.aggregate_children.sort_by(&:total_time).reverse %>
232
+ <% next if min_time && callee.total_time < min_time %>
233
+ <tr>
234
+ <td>&nbsp;</td>
235
+ <td>&nbsp;</td>
236
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.total_time) %></td>
237
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.self_time) %></td>
238
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.wait_time) %></td>
239
+ <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.children_time) %></td>
240
+ <% called = "#{callee.called}/#{callee.target.called}" %>
241
+ <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
242
+ <td class="method_name"><%= create_link(thread_id, callee.target) %></td>
243
+ <td><a href="file://<%=h srcfile=File.expand_path(method.source_file) %>#line=<%= linenum=callee.line %>" title="<%=h srcfile %>:<%= linenum %>"><%= callee.line %></a></td>
244
+ </tr>
245
+ <% end %>
246
+ <!-- Create divider row -->
247
+ <tr class="break"><td colspan="9"></td></tr>
248
+ <% end %>
249
+ </table>
250
+ <% end %>
251
+ </body>
252
+ </html>'
253
+ end
254
+ end
255
+ end
256
+
@@ -0,0 +1,157 @@
1
+ require 'ruby-prof/abstract_printer'
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, 5)
12
+ # printer.print(STDOUT, 0)
13
+ #
14
+ # The constructor takes two arguments. See the README
15
+
16
+ class GraphPrinter < AbstractPrinter
17
+ PERCENTAGE_WIDTH = 8
18
+ TIME_WIDTH = 10
19
+ CALL_WIDTH = 17
20
+
21
+ # Create a GraphPrinter. Result is a RubyProf::Result
22
+ # object generated from a profiling run.
23
+ def initialize(result)
24
+ super(result)
25
+ @thread_times = Hash.new
26
+ calculate_thread_times
27
+ end
28
+
29
+ def calculate_thread_times
30
+ # Cache thread times since this is an expensive
31
+ # operation with the required sorting
32
+ @result.threads.each do |thread_id, methods|
33
+ top = methods.max
34
+
35
+ thread_time = [top.total_time, 0.01].max
36
+
37
+ @thread_times[thread_id] = thread_time
38
+ end
39
+ end
40
+
41
+ # Print a graph report to the provided output.
42
+ #
43
+ # output - Any IO oject, including STDOUT or a file.
44
+ # The default value is STDOUT.
45
+ #
46
+ # options - Hash of print options. See #setup_options
47
+ # for more information.
48
+ #
49
+ def print(output = STDOUT, options = {})
50
+ @output = output
51
+ setup_options(options)
52
+ print_threads
53
+ end
54
+
55
+ private
56
+ def print_threads
57
+ # sort assumes that spawned threads have higher object_ids
58
+ @result.threads.sort.each do |thread_id, methods|
59
+ print_methods(thread_id, methods)
60
+ @output << "\n" * 2
61
+ end
62
+ end
63
+
64
+ def print_methods(thread_id, methods)
65
+ # Sort methods from longest to shortest total time
66
+ methods = methods.sort
67
+
68
+ toplevel = methods.last
69
+ total_time = toplevel.total_time
70
+ if total_time == 0
71
+ total_time = 0.01
72
+ end
73
+
74
+ print_heading(thread_id)
75
+
76
+ # Print each method in total time order
77
+ methods.reverse_each do |method|
78
+ total_percentage = (method.total_time/total_time) * 100
79
+ self_percentage = (method.self_time/total_time) * 100
80
+
81
+ next if total_percentage < min_percent
82
+
83
+ @output << "-" * 80 << "\n"
84
+
85
+ print_parents(thread_id, method)
86
+
87
+ # 1 is for % sign
88
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage)
89
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage)
90
+ @output << sprintf("%#{TIME_WIDTH}.2f", method.total_time)
91
+ @output << sprintf("%#{TIME_WIDTH}.2f", method.self_time)
92
+ @output << sprintf("%#{TIME_WIDTH}.2f", method.wait_time)
93
+ @output << sprintf("%#{TIME_WIDTH}.2f", method.children_time)
94
+ @output << sprintf("%#{CALL_WIDTH}i", method.called)
95
+ @output << sprintf(" %s", method_name(method))
96
+ if print_file
97
+ @output << sprintf(" %s:%s", method.source_file, method.line)
98
+ end
99
+ @output << "\n"
100
+
101
+ print_children(method)
102
+ end
103
+ end
104
+
105
+ def print_heading(thread_id)
106
+ @output << "Thread ID: #{thread_id}\n"
107
+ @output << "Total Time: #{@thread_times[thread_id]}\n"
108
+ @output << "\n"
109
+
110
+ # 1 is for % sign
111
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
112
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
113
+ @output << sprintf("%#{TIME_WIDTH}s", "total")
114
+ @output << sprintf("%#{TIME_WIDTH}s", "self")
115
+ @output << sprintf("%#{TIME_WIDTH}s", "wait")
116
+ @output << sprintf("%#{TIME_WIDTH}s", "child")
117
+ @output << sprintf("%#{CALL_WIDTH}s", "calls")
118
+ @output << " Name"
119
+ @output << "\n"
120
+ end
121
+
122
+ def print_parents(thread_id, method)
123
+ method.aggregate_parents.sort_by(&:total_time).each do |caller|
124
+ next unless caller.parent
125
+ @output << " " * 2 * PERCENTAGE_WIDTH
126
+ @output << sprintf("%#{TIME_WIDTH}.2f", caller.total_time)
127
+ @output << sprintf("%#{TIME_WIDTH}.2f", caller.self_time)
128
+ @output << sprintf("%#{TIME_WIDTH}.2f", caller.wait_time)
129
+ @output << sprintf("%#{TIME_WIDTH}.2f", caller.children_time)
130
+
131
+ call_called = "#{caller.called}/#{method.called}"
132
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
133
+ @output << sprintf(" %s", caller.parent.target.full_name)
134
+ @output << "\n"
135
+ end
136
+ end
137
+
138
+ def print_children(method)
139
+ method.aggregate_children.sort_by(&:total_time).reverse.each do |child|
140
+ # Get children method
141
+
142
+ @output << " " * 2 * PERCENTAGE_WIDTH
143
+
144
+ @output << sprintf("%#{TIME_WIDTH}.2f", child.total_time)
145
+ @output << sprintf("%#{TIME_WIDTH}.2f", child.self_time)
146
+ @output << sprintf("%#{TIME_WIDTH}.2f", child.wait_time)
147
+ @output << sprintf("%#{TIME_WIDTH}.2f", child.children_time)
148
+
149
+ call_called = "#{child.called}/#{child.target.called}"
150
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
151
+ @output << sprintf(" %s", child.target.full_name)
152
+ @output << "\n"
153
+ end
154
+ end
155
+ end
156
+ end
157
+