ruby-prof 0.13.1 → 1.4.2

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 (209) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +579 -371
  3. data/LICENSE +24 -23
  4. data/README.rdoc +5 -433
  5. data/Rakefile +98 -110
  6. data/bin/ruby-prof +328 -329
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +16 -59
  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 +369 -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 +50 -65
  18. data/ext/ruby_prof/rp_measure_memory.c +42 -73
  19. data/ext/ruby_prof/rp_measure_process_time.c +65 -71
  20. data/ext/ruby_prof/rp_measure_wall_time.c +64 -42
  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 -420
  24. data/ext/ruby_prof/rp_method.h +62 -57
  25. data/ext/ruby_prof/rp_profile.c +908 -0
  26. data/ext/ruby_prof/rp_profile.h +35 -0
  27. data/ext/ruby_prof/rp_stack.c +212 -128
  28. data/ext/ruby_prof/rp_stack.h +53 -51
  29. data/ext/ruby_prof/rp_thread.c +362 -268
  30. data/ext/ruby_prof/rp_thread.h +39 -27
  31. data/ext/ruby_prof/ruby_prof.c +52 -695
  32. data/ext/ruby_prof/ruby_prof.h +26 -55
  33. data/ext/ruby_prof/vc/ruby_prof.sln +28 -21
  34. data/ext/ruby_prof/vc/{ruby_prof_20.vcxproj → ruby_prof.vcxproj} +56 -8
  35. data/lib/ruby-prof.rb +52 -67
  36. data/lib/ruby-prof/assets/call_stack_printer.html.erb +710 -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 -169
  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 -131
  45. data/lib/ruby-prof/printers/abstract_printer.rb +137 -85
  46. data/lib/ruby-prof/printers/call_info_printer.rb +53 -41
  47. data/lib/ruby-prof/printers/call_stack_printer.rb +180 -773
  48. data/lib/ruby-prof/printers/call_tree_printer.rb +151 -92
  49. data/lib/ruby-prof/printers/dot_printer.rb +132 -132
  50. data/lib/ruby-prof/printers/flat_printer.rb +53 -69
  51. data/lib/ruby-prof/printers/graph_html_printer.rb +63 -255
  52. data/lib/ruby-prof/printers/graph_printer.rb +113 -116
  53. data/lib/ruby-prof/printers/multi_printer.rb +127 -56
  54. data/lib/ruby-prof/profile.rb +37 -77
  55. data/lib/ruby-prof/rack.rb +62 -15
  56. data/lib/ruby-prof/task.rb +147 -147
  57. data/lib/ruby-prof/thread.rb +10 -12
  58. data/lib/ruby-prof/version.rb +3 -0
  59. data/lib/unprof.rb +10 -10
  60. data/ruby-prof.gemspec +65 -61
  61. data/test/abstract_printer_test.rb +26 -0
  62. data/test/alias_test.rb +126 -0
  63. data/test/basic_test.rb +43 -128
  64. data/test/call_tree_visitor_test.rb +32 -0
  65. data/test/call_trees_test.rb +66 -0
  66. data/test/duplicate_names_test.rb +32 -32
  67. data/test/dynamic_method_test.rb +53 -74
  68. data/test/enumerable_test.rb +21 -16
  69. data/test/exceptions_test.rb +24 -16
  70. data/test/exclude_methods_test.rb +151 -0
  71. data/test/exclude_threads_test.rb +53 -54
  72. data/test/fiber_test.rb +129 -65
  73. data/test/gc_test.rb +90 -0
  74. data/test/inverse_call_tree_test.rb +175 -0
  75. data/test/line_number_test.rb +158 -71
  76. data/test/marshal_test.rb +113 -0
  77. data/test/measure_allocations.rb +30 -0
  78. data/test/measure_allocations_test.rb +375 -25
  79. data/test/measure_allocations_trace_test.rb +375 -0
  80. data/test/measure_memory_trace_test.rb +1101 -0
  81. data/test/measure_process_time_test.rb +785 -62
  82. data/test/measure_times.rb +56 -0
  83. data/test/measure_wall_time_test.rb +434 -254
  84. data/test/multi_printer_test.rb +71 -82
  85. data/test/no_method_class_test.rb +15 -15
  86. data/test/pause_resume_test.rb +175 -166
  87. data/test/prime.rb +54 -54
  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 -257
  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 +206 -215
  99. data/test/singleton_test.rb +38 -38
  100. data/test/stack_printer_test.rb +64 -78
  101. data/test/start_stop_test.rb +109 -112
  102. data/test/test_helper.rb +13 -115
  103. data/test/thread_test.rb +144 -178
  104. data/test/unique_call_path_test.rb +120 -224
  105. data/test/yarv_test.rb +56 -0
  106. metadata +77 -133
  107. data/doc/LICENSE.html +0 -155
  108. data/doc/README_rdoc.html +0 -648
  109. data/doc/Rack.html +0 -167
  110. data/doc/Rack/RubyProf.html +0 -319
  111. data/doc/RubyProf.html +0 -1000
  112. data/doc/RubyProf/AbstractPrinter.html +0 -580
  113. data/doc/RubyProf/AggregateCallInfo.html +0 -570
  114. data/doc/RubyProf/CallInfo.html +0 -512
  115. data/doc/RubyProf/CallInfoPrinter.html +0 -190
  116. data/doc/RubyProf/CallInfoVisitor.html +0 -332
  117. data/doc/RubyProf/CallStackPrinter.html +0 -1600
  118. data/doc/RubyProf/CallTreePrinter.html +0 -413
  119. data/doc/RubyProf/Cmd.html +0 -669
  120. data/doc/RubyProf/DotPrinter.html +0 -312
  121. data/doc/RubyProf/FlatPrinter.html +0 -229
  122. data/doc/RubyProf/FlatPrinterWithLineNumbers.html +0 -267
  123. data/doc/RubyProf/GraphHtmlPrinter.html +0 -630
  124. data/doc/RubyProf/GraphPrinter.html +0 -209
  125. data/doc/RubyProf/MethodInfo.html +0 -713
  126. data/doc/RubyProf/MultiPrinter.html +0 -407
  127. data/doc/RubyProf/Profile.html +0 -821
  128. data/doc/RubyProf/ProfileTask.html +0 -532
  129. data/doc/RubyProf/Test.html +0 -578
  130. data/doc/RubyProf/Thread.html +0 -262
  131. data/doc/created.rid +0 -32
  132. data/doc/examples/flat_txt.html +0 -191
  133. data/doc/examples/graph_txt.html +0 -305
  134. data/doc/images/add.png +0 -0
  135. data/doc/images/brick.png +0 -0
  136. data/doc/images/brick_link.png +0 -0
  137. data/doc/images/bug.png +0 -0
  138. data/doc/images/bullet_black.png +0 -0
  139. data/doc/images/bullet_toggle_minus.png +0 -0
  140. data/doc/images/bullet_toggle_plus.png +0 -0
  141. data/doc/images/date.png +0 -0
  142. data/doc/images/delete.png +0 -0
  143. data/doc/images/find.png +0 -0
  144. data/doc/images/loadingAnimation.gif +0 -0
  145. data/doc/images/macFFBgHack.png +0 -0
  146. data/doc/images/package.png +0 -0
  147. data/doc/images/page_green.png +0 -0
  148. data/doc/images/page_white_text.png +0 -0
  149. data/doc/images/page_white_width.png +0 -0
  150. data/doc/images/plugin.png +0 -0
  151. data/doc/images/ruby.png +0 -0
  152. data/doc/images/tag_blue.png +0 -0
  153. data/doc/images/tag_green.png +0 -0
  154. data/doc/images/transparent.png +0 -0
  155. data/doc/images/wrench.png +0 -0
  156. data/doc/images/wrench_orange.png +0 -0
  157. data/doc/images/zoom.png +0 -0
  158. data/doc/index.html +0 -647
  159. data/doc/js/darkfish.js +0 -155
  160. data/doc/js/jquery.js +0 -18
  161. data/doc/js/navigation.js +0 -142
  162. data/doc/js/search.js +0 -94
  163. data/doc/js/search_index.js +0 -1
  164. data/doc/js/searcher.js +0 -228
  165. data/doc/rdoc.css +0 -543
  166. data/doc/table_of_contents.html +0 -462
  167. data/examples/empty.png +0 -0
  168. data/examples/flat.txt +0 -55
  169. data/examples/graph.dot +0 -106
  170. data/examples/graph.html +0 -823
  171. data/examples/graph.png +0 -0
  172. data/examples/graph.txt +0 -170
  173. data/examples/minus.png +0 -0
  174. data/examples/multi.flat.txt +0 -23
  175. data/examples/multi.graph.html +0 -906
  176. data/examples/multi.grind.dat +0 -194
  177. data/examples/multi.stack.html +0 -573
  178. data/examples/plus.png +0 -0
  179. data/examples/stack.html +0 -573
  180. data/ext/ruby_prof/rp_call_info.c +0 -407
  181. data/ext/ruby_prof/rp_call_info.h +0 -48
  182. data/ext/ruby_prof/rp_measure.c +0 -48
  183. data/ext/ruby_prof/rp_measure.h +0 -45
  184. data/ext/ruby_prof/rp_measure_cpu_time.c +0 -112
  185. data/ext/ruby_prof/rp_measure_gc_runs.c +0 -65
  186. data/ext/ruby_prof/rp_measure_gc_time.c +0 -57
  187. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +0 -108
  188. data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +0 -110
  189. data/ext/ruby_prof/version.h +0 -7
  190. data/lib/ruby-prof/aggregate_call_info.rb +0 -72
  191. data/lib/ruby-prof/call_info.rb +0 -89
  192. data/lib/ruby-prof/call_info_visitor.rb +0 -44
  193. data/lib/ruby-prof/images/empty.png +0 -0
  194. data/lib/ruby-prof/images/minus.png +0 -0
  195. data/lib/ruby-prof/images/plus.png +0 -0
  196. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -57
  197. data/lib/ruby-prof/test.rb +0 -150
  198. data/test/aggregate_test.rb +0 -136
  199. data/test/call_info_test.rb +0 -78
  200. data/test/call_info_visitor_test.rb +0 -31
  201. data/test/exec_test.rb +0 -14
  202. data/test/measure_cpu_time_test.rb +0 -220
  203. data/test/measure_gc_runs_test.rb +0 -32
  204. data/test/measure_gc_time_test.rb +0 -36
  205. data/test/measure_memory_test.rb +0 -31
  206. data/test/method_elimination_test.rb +0 -84
  207. data/test/module_test.rb +0 -45
  208. data/test/stack_test.rb +0 -138
  209. data/test/test_suite.rb +0 -37
@@ -1,69 +1,53 @@
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 << "Thread ID: %d\n" % thread.id
31
- @output << "Fiber ID: %d\n" % thread.fiber_id unless thread.id == thread.fiber_id
32
- @output << "Total: %0.6f\n" % thread.total_time
33
- @output << "Sort by: #{sort_method}\n"
34
- @output << "\n"
35
- @output << " %self total self wait child calls name\n"
36
- end
37
-
38
- def print_methods(thread)
39
- total_time = thread.total_time
40
- methods = thread.methods.sort_by(&sort_method).reverse
41
-
42
- sum = 0
43
- methods.each do |method|
44
- self_percent = (method.self_time / total_time) * 100
45
- next if self_percent < min_percent
46
-
47
- sum += method.self_time
48
- #self_time_called = method.called > 0 ? method.self_time/method.called : 0
49
- #total_time_called = method.called > 0? method.total_time/method.called : 0
50
-
51
- @output << "%6.2f %9.3f %9.3f %9.3f %9.3f %8d %s%s \n" % [
52
- method.self_time / total_time * 100, # %self
53
- method.total_time, # total
54
- method.self_time, # self
55
- method.wait_time, # wait
56
- method.children_time, # children
57
- method.called, # calls
58
- method.recursive? ? "*" : " ", # cycle
59
- method_name(method) # name
60
- ]
61
- end
62
- end
63
-
64
- def print_footer(thread)
65
- @output << "\n"
66
- @output << "* indicates recursively called methods\n"
67
- end
68
- end
69
- end
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_column_headers
23
+ @output << " %self total self wait child calls name location\n"
24
+ end
25
+
26
+ def print_methods(thread)
27
+ total_time = thread.total_time
28
+ methods = thread.methods.sort_by(&sort_method).reverse
29
+
30
+ sum = 0
31
+ methods.each do |method|
32
+ percent = (method.send(filter_by) / total_time) * 100
33
+ next if percent < min_percent
34
+ next if percent > max_percent
35
+
36
+ sum += method.self_time
37
+ #self_time_called = method.called > 0 ? method.self_time/method.called : 0
38
+ #total_time_called = method.called > 0? method.total_time/method.called : 0
39
+
40
+ @output << "%6.2f %9.3f %9.3f %9.3f %9.3f %8d %s%-30s %s\n" % [
41
+ method.self_time / total_time * 100, # %self
42
+ method.total_time, # total
43
+ method.self_time, # self
44
+ method.wait_time, # wait
45
+ method.children_time, # children
46
+ method.called, # calls
47
+ method.recursive? ? "*" : " ", # cycle
48
+ method.full_name, # method_name]
49
+ method_location(method)] # location]
50
+ end
51
+ end
52
+ end
53
+ end
@@ -1,255 +1,63 @@
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
-
24
- class GraphHtmlPrinter < AbstractPrinter
25
- include ERB::Util
26
-
27
- PERCENTAGE_WIDTH = 8
28
- TIME_WIDTH = 10
29
- CALL_WIDTH = 20
30
-
31
- def setup_options(options)
32
- super(options)
33
-
34
- filename = options[:filename]
35
- template = filename ? File.read(filename).untaint : (options[:template] || self.template)
36
- @erb = ERB.new(template, nil, nil)
37
- @erb.filename = filename
38
- end
39
-
40
- def print(output = STDOUT, options = {})
41
- @output = output
42
- setup_options(options)
43
- @output << @erb.result(binding)
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 RUBY_PLATFORM =~ /darwin/
71
- "<a href=\"txmt://open?url=file://#{h srcfile}&line=#{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
72
- else
73
- "<a href=\"file://#{h srcfile}##{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
74
- end
75
- end
76
- end
77
-
78
- def template
79
- '
80
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
81
- <html>
82
- <head>
83
- <style media="all" type="text/css">
84
- table {
85
- border-collapse: collapse;
86
- border: 1px solid #CCC;
87
- font-family: Verdana, Arial, Helvetica, sans-serif;
88
- font-size: 9pt;
89
- line-height: normal;
90
- width: 100%;
91
- }
92
-
93
- th {
94
- text-align: center;
95
- border-top: 1px solid #FB7A31;
96
- border-bottom: 1px solid #FB7A31;
97
- background: #FFC;
98
- padding: 0.3em;
99
- border-left: 1px solid silver;
100
- }
101
-
102
- tr.break td {
103
- border: 0;
104
- border-top: 1px solid #FB7A31;
105
- padding: 0;
106
- margin: 0;
107
- }
108
-
109
- tr.method td {
110
- font-weight: bold;
111
- }
112
-
113
- td {
114
- padding: 0.3em;
115
- }
116
-
117
- td:first-child {
118
- width: 190px;
119
- }
120
-
121
- td {
122
- border-left: 1px solid #CCC;
123
- text-align: center;
124
- }
125
-
126
- .method_name {
127
- text-align: left;
128
- }
129
-
130
- tfoot td {
131
- text-align: left;
132
- }
133
- </style>
134
- </head>
135
- <body>
136
- <h1>Profile Report</h1>
137
- <!-- Threads Table -->
138
- <table>
139
- <tr>
140
- <th>Thread ID</th>
141
- <% if RUBY_VERSION >= "1.9" %>
142
- <th>Fiber ID</th>
143
- <% end %>
144
- <th>Total Time</th>
145
- </tr>
146
- <% for thread in @result.threads %>
147
- <tr>
148
- <% if RUBY_VERSION >= "1.9" %>
149
- <td><%= thread.id %></td>
150
- <% end %>
151
- <td><a href="#<%= thread.fiber_id %>"><%= thread.fiber_id %></a></td>
152
- <td><%= thread.total_time %></td>
153
- </tr>
154
- <% end %>
155
- </table>
156
-
157
- <!-- Methods Tables -->
158
- <% for thread in @result.threads
159
- methods = thread.methods
160
- total_time = thread.total_time %>
161
- <% if RUBY_VERSION >= "1.9" %>
162
- <h2><a name="<%= thread.fiber_id %>">Thread <%= thread.id %>, Fiber: <%= thread.fiber_id %></a></h2>
163
- <% else %>
164
- <h2><a name="<%= thread.fiber_id %>">Thread <%= thread.fiber_id %></a></h2>
165
- <% end %>
166
- <table>
167
- <thead>
168
- <tr>
169
- <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Total") %></th>
170
- <th><%= sprintf("%#{PERCENTAGE_WIDTH}s", "%Self") %></th>
171
- <th><%= sprintf("%#{TIME_WIDTH}s", "Total") %></th>
172
- <th><%= sprintf("%#{TIME_WIDTH}s", "Self") %></th>
173
- <th><%= sprintf("%#{TIME_WIDTH}s", "Wait") %></th>
174
- <th><%= sprintf("%#{TIME_WIDTH+2}s", "Child") %></th>
175
- <th><%= sprintf("%#{CALL_WIDTH}s", "Calls") %></th>
176
- <th class="method_name">Name</th>
177
- <th>Line</th>
178
- </tr>
179
- </thead>
180
-
181
- <tbody>
182
- <% min_time = @options[:min_time] || (@options[:nonzero] ? 0.005 : nil)
183
- methods.sort_by(&sort_method).reverse_each do |method|
184
- total_percentage = (method.total_time/total_time) * 100
185
- next if total_percentage < min_percent
186
- next if min_time && method.total_time < min_time
187
- self_percentage = (method.self_time/total_time) * 100 %>
188
-
189
- <!-- Parents -->
190
- <% for caller in method.aggregate_parents.sort_by(&:total_time)
191
- next unless caller.parent
192
- next if min_time && caller.total_time < min_time %>
193
- <tr>
194
- <td>&nbsp;</td>
195
- <td>&nbsp;</td>
196
- <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.total_time) %></td>
197
- <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.self_time) %></td>
198
- <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.wait_time) %></td>
199
- <td><%= sprintf("%#{TIME_WIDTH}.2f", caller.children_time) %></td>
200
- <% called = "#{caller.called}/#{method.called}" %>
201
- <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
202
- <td class="method_name"><%= create_link(thread, total_time, caller.parent.target) %></td>
203
- <td><%= file_link(caller.parent.target.source_file, caller.line) %></td>
204
- </tr>
205
- <% end %>
206
-
207
- <tr class="method">
208
- <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", total_percentage) %></td>
209
- <td><%= sprintf("%#{PERCENTAGE_WIDTH-1}.2f\%", self_percentage) %></td>
210
- <td><%= sprintf("%#{TIME_WIDTH}.2f", method.total_time) %></td>
211
- <td><%= sprintf("%#{TIME_WIDTH}.2f", method.self_time) %></td>
212
- <td><%= sprintf("%#{TIME_WIDTH}.2f", method.wait_time) %></td>
213
- <td><%= sprintf("%#{TIME_WIDTH}.2f", method.children_time) %></td>
214
- <td><%= sprintf("%#{CALL_WIDTH}i", method.called) %></td>
215
- <td class="method_name">
216
- <a name="<%= method_href(thread, method) %>">
217
- <%= method.recursive? ? "*" : " "%><%= h method.full_name %>
218
- </a>
219
- </td>
220
- <td><%= file_link(method.source_file, method.line) %></td>
221
- </tr>
222
-
223
- <!-- Children -->
224
- <% for callee in method.aggregate_children.sort_by(&:total_time).reverse %>
225
- <% next if min_time && callee.total_time < min_time %>
226
- <tr>
227
- <td>&nbsp;</td>
228
- <td>&nbsp;</td>
229
- <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.total_time) %></td>
230
- <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.self_time) %></td>
231
- <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.wait_time) %></td>
232
- <td><%= sprintf("%#{TIME_WIDTH}.2f", callee.children_time) %></td>
233
- <% called = "#{callee.called}/#{callee.target.called}" %>
234
- <td><%= sprintf("%#{CALL_WIDTH}s", called) %></td>
235
- <td class="method_name"><%= create_link(thread, total_time, callee.target) %></td>
236
- <td><%= file_link(method.source_file, callee.line) %></td>
237
- </tr>
238
- <% end %>
239
- <!-- Create divider row -->
240
- <tr class="break"><td colspan="9"></td></tr>
241
- <% end %>
242
- </tbody>
243
- <tfoot>
244
- <tr>
245
- <td colspan="9">* indicates recursively called methods</td>
246
- </tr>
247
- </tfoot>
248
- </table>
249
- <% end %>
250
- </body>
251
- </html>'
252
- end
253
- end
254
- end
255
-
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
+
18
+ class GraphHtmlPrinter < AbstractPrinter
19
+ include ERB::Util
20
+
21
+ def setup_options(options)
22
+ super(options)
23
+ @erb = ERB.new(self.template)
24
+ end
25
+
26
+ def print(output = STDOUT, options = {})
27
+ setup_options(options)
28
+ output << @erb.result(binding)
29
+ end
30
+
31
+ # Creates a link to a method. Note that we do not create
32
+ # links to methods which are under the min_perecent
33
+ # specified by the user, since they will not be
34
+ # printed out.
35
+ def create_link(thread, overall_time, method)
36
+ total_percent = (method.total_time/overall_time) * 100
37
+ if total_percent < min_percent
38
+ # Just return name
39
+ h method.full_name
40
+ else
41
+ href = '#' + method_href(thread, method)
42
+ "<a href=\"#{href}\">#{h method.full_name}</a>"
43
+ end
44
+ end
45
+
46
+ def method_href(thread, method)
47
+ h(method.full_name.gsub(/[><#\.\?=:]/,"_") + "_" + thread.fiber_id.to_s)
48
+ end
49
+
50
+ def file_link(path, linenum)
51
+ if path.nil?
52
+ ""
53
+ else
54
+ srcfile = File.expand_path(path)
55
+ "<a href=\"file://#{h srcfile}##{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
56
+ end
57
+ end
58
+
59
+ def template
60
+ open_asset('graph_printer.html.erb')
61
+ end
62
+ end
63
+ end
@@ -1,116 +1,113 @@
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 << "Thread ID: #{thread.id}\n"
25
- @output << "Fiber ID: #{thread.fiber_id}\n" unless thread.id == thread.fiber_id
26
- @output << "Total Time: #{thread.total_time}\n"
27
- @output << "Sort by: #{sort_method}\n"
28
- @output << "\n"
29
-
30
- # 1 is for % sign
31
- @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
32
- @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
33
- @output << sprintf("%#{TIME_WIDTH}s", "total")
34
- @output << sprintf("%#{TIME_WIDTH}s", "self")
35
- @output << sprintf("%#{TIME_WIDTH}s", "wait")
36
- @output << sprintf("%#{TIME_WIDTH}s", "child")
37
- @output << sprintf("%#{CALL_WIDTH}s", "calls")
38
- @output << " Name"
39
- @output << "\n"
40
- end
41
-
42
- def print_methods(thread)
43
- total_time = thread.total_time
44
- # Sort methods from longest to shortest total time
45
- methods = thread.methods.sort_by(&sort_method)
46
-
47
- # Print each method in total time order
48
- methods.reverse_each do |method|
49
- total_percentage = (method.total_time/total_time) * 100
50
- self_percentage = (method.self_time/total_time) * 100
51
-
52
- next if total_percentage < min_percent
53
-
54
- @output << "-" * 80 << "\n"
55
-
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
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 sort_method
24
+ @options[:sort_method] || :total_time
25
+ end
26
+
27
+ def print_header(thread)
28
+ @output << "Measure Mode: %s\n" % @result.measure_mode_string
29
+ @output << "Thread ID: #{thread.id}\n"
30
+ @output << "Fiber ID: #{thread.fiber_id}\n"
31
+ @output << "Total Time: #{thread.total_time}\n"
32
+ @output << "Sort by: #{sort_method}\n"
33
+ @output << "\n"
34
+
35
+ # 1 is for % sign
36
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%total")
37
+ @output << sprintf("%#{PERCENTAGE_WIDTH}s", "%self")
38
+ @output << sprintf("%#{TIME_WIDTH}s", "total")
39
+ @output << sprintf("%#{TIME_WIDTH}s", "self")
40
+ @output << sprintf("%#{TIME_WIDTH}s", "wait")
41
+ @output << sprintf("%#{TIME_WIDTH}s", "child")
42
+ @output << sprintf("%#{CALL_WIDTH}s", "calls")
43
+ @output << " name"
44
+ @output << " location"
45
+ @output << "\n"
46
+ end
47
+
48
+ def print_methods(thread)
49
+ total_time = thread.total_time
50
+ # Sort methods from longest to shortest total time
51
+ methods = thread.methods.sort_by(&sort_method)
52
+
53
+ # Print each method in total time order
54
+ methods.reverse_each do |method|
55
+ total_percentage = (method.total_time/total_time) * 100
56
+ next if total_percentage < min_percent
57
+
58
+ self_percentage = (method.self_time/total_time) * 100
59
+
60
+ @output << "-" * 150 << "\n"
61
+ print_parents(thread, method)
62
+
63
+ # 1 is for % sign
64
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", total_percentage)
65
+ @output << sprintf("%#{PERCENTAGE_WIDTH-1}.2f%%", self_percentage)
66
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.total_time)
67
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.self_time)
68
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.wait_time)
69
+ @output << sprintf("%#{TIME_WIDTH}.3f", method.children_time)
70
+ @output << sprintf("%#{CALL_WIDTH}i", method.called)
71
+ @output << sprintf(" %s", method.recursive? ? "*" : " ")
72
+ @output << sprintf("%-30s", method.full_name)
73
+ @output << sprintf(" %s", method_location(method))
74
+ @output << "\n"
75
+
76
+ print_children(method)
77
+ end
78
+ end
79
+
80
+ def print_parents(thread, method)
81
+ method.call_trees.callers.sort_by(&:total_time).each do |caller|
82
+ @output << " " * 2 * PERCENTAGE_WIDTH
83
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.total_time)
84
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.self_time)
85
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.wait_time)
86
+ @output << sprintf("%#{TIME_WIDTH}.3f", caller.children_time)
87
+
88
+ call_called = "#{caller.called}/#{method.called}"
89
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
90
+ @output << sprintf(" %s", caller.parent.target.full_name)
91
+ @output << "\n"
92
+ end
93
+ end
94
+
95
+ def print_children(method)
96
+ method.call_trees.callees.sort_by(&:total_time).reverse.each do |child|
97
+ # Get children method
98
+
99
+ @output << " " * 2 * PERCENTAGE_WIDTH
100
+
101
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.total_time)
102
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.self_time)
103
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.wait_time)
104
+ @output << sprintf("%#{TIME_WIDTH}.3f", child.children_time)
105
+
106
+ call_called = "#{child.called}/#{child.target.called}"
107
+ @output << sprintf("%#{CALL_WIDTH}s", call_called)
108
+ @output << sprintf(" %s", child.target.full_name)
109
+ @output << "\n"
110
+ end
111
+ end
112
+ end
113
+ end