ruby-prof 0.17.0 → 0.18.0

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 (185) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGES +500 -482
  3. data/LICENSE +24 -24
  4. data/README.rdoc +487 -485
  5. data/Rakefile +113 -113
  6. data/bin/ruby-prof +345 -345
  7. data/bin/ruby-prof-check-trace +45 -45
  8. data/examples/flat.txt +50 -50
  9. data/examples/graph.dot +84 -84
  10. data/examples/graph.html +823 -823
  11. data/examples/graph.txt +139 -139
  12. data/examples/multi.flat.txt +23 -23
  13. data/examples/multi.graph.html +760 -760
  14. data/examples/multi.grind.dat +114 -114
  15. data/examples/multi.stack.html +547 -547
  16. data/examples/stack.html +547 -547
  17. data/ext/ruby_prof/extconf.rb +68 -68
  18. data/ext/ruby_prof/rp_call_info.c +425 -425
  19. data/ext/ruby_prof/rp_call_info.h +53 -53
  20. data/ext/ruby_prof/rp_measure.c +40 -40
  21. data/ext/ruby_prof/rp_measure.h +45 -45
  22. data/ext/ruby_prof/rp_measure_allocations.c +76 -76
  23. data/ext/ruby_prof/rp_measure_cpu_time.c +136 -136
  24. data/ext/ruby_prof/rp_measure_gc_runs.c +73 -73
  25. data/ext/ruby_prof/rp_measure_gc_time.c +60 -60
  26. data/ext/ruby_prof/rp_measure_memory.c +77 -77
  27. data/ext/ruby_prof/rp_measure_process_time.c +71 -71
  28. data/ext/ruby_prof/rp_measure_wall_time.c +45 -45
  29. data/ext/ruby_prof/rp_method.c +630 -636
  30. data/ext/ruby_prof/rp_method.h +75 -75
  31. data/ext/ruby_prof/rp_stack.c +173 -173
  32. data/ext/ruby_prof/rp_stack.h +63 -63
  33. data/ext/ruby_prof/rp_thread.c +277 -276
  34. data/ext/ruby_prof/rp_thread.h +27 -27
  35. data/ext/ruby_prof/ruby_prof.c +794 -774
  36. data/ext/ruby_prof/ruby_prof.h +60 -59
  37. data/ext/ruby_prof/vc/ruby_prof.sln +20 -21
  38. data/ext/ruby_prof/vc/{ruby_prof_20.vcxproj → ruby_prof.vcxproj} +31 -0
  39. data/lib/ruby-prof.rb +68 -68
  40. data/lib/ruby-prof/aggregate_call_info.rb +76 -76
  41. data/lib/ruby-prof/assets/call_stack_printer.css.html +116 -116
  42. data/lib/ruby-prof/assets/call_stack_printer.js.html +384 -384
  43. data/lib/ruby-prof/call_info.rb +115 -115
  44. data/lib/ruby-prof/call_info_visitor.rb +40 -40
  45. data/lib/ruby-prof/compatibility.rb +179 -178
  46. data/lib/ruby-prof/method_info.rb +121 -121
  47. data/lib/ruby-prof/printers/abstract_printer.rb +104 -103
  48. data/lib/ruby-prof/printers/call_info_printer.rb +41 -41
  49. data/lib/ruby-prof/printers/call_stack_printer.rb +265 -265
  50. data/lib/ruby-prof/printers/call_tree_printer.rb +143 -143
  51. data/lib/ruby-prof/printers/dot_printer.rb +132 -132
  52. data/lib/ruby-prof/printers/flat_printer.rb +70 -70
  53. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +83 -83
  54. data/lib/ruby-prof/printers/graph_html_printer.rb +249 -249
  55. data/lib/ruby-prof/printers/graph_printer.rb +116 -116
  56. data/lib/ruby-prof/printers/multi_printer.rb +84 -84
  57. data/lib/ruby-prof/profile.rb +26 -26
  58. data/lib/ruby-prof/profile/exclude_common_methods.rb +207 -201
  59. data/lib/ruby-prof/profile/legacy_method_elimination.rb +50 -49
  60. data/lib/ruby-prof/rack.rb +174 -174
  61. data/lib/ruby-prof/task.rb +147 -147
  62. data/lib/ruby-prof/thread.rb +35 -35
  63. data/lib/ruby-prof/version.rb +3 -3
  64. data/lib/unprof.rb +10 -10
  65. data/ruby-prof.gemspec +58 -58
  66. data/test/abstract_printer_test.rb +53 -0
  67. data/test/aggregate_test.rb +136 -136
  68. data/test/basic_test.rb +128 -128
  69. data/test/block_test.rb +74 -74
  70. data/test/call_info_test.rb +78 -78
  71. data/test/call_info_visitor_test.rb +31 -31
  72. data/test/duplicate_names_test.rb +32 -32
  73. data/test/dynamic_method_test.rb +55 -55
  74. data/test/enumerable_test.rb +21 -21
  75. data/test/exceptions_test.rb +24 -16
  76. data/test/exclude_methods_test.rb +146 -146
  77. data/test/exclude_threads_test.rb +53 -53
  78. data/test/fiber_test.rb +79 -79
  79. data/test/issue137_test.rb +63 -63
  80. data/test/line_number_test.rb +80 -80
  81. data/test/measure_allocations_test.rb +26 -26
  82. data/test/measure_cpu_time_test.rb +212 -213
  83. data/test/measure_gc_runs_test.rb +32 -32
  84. data/test/measure_gc_time_test.rb +36 -36
  85. data/test/measure_memory_test.rb +33 -33
  86. data/test/measure_process_time_test.rb +61 -63
  87. data/test/measure_wall_time_test.rb +255 -255
  88. data/test/method_elimination_test.rb +84 -84
  89. data/test/module_test.rb +45 -45
  90. data/test/multi_printer_test.rb +104 -104
  91. data/test/no_method_class_test.rb +15 -15
  92. data/test/pause_resume_test.rb +166 -166
  93. data/test/prime.rb +54 -54
  94. data/test/printers_test.rb +275 -275
  95. data/test/printing_recursive_graph_test.rb +127 -127
  96. data/test/rack_test.rb +157 -157
  97. data/test/recursive_test.rb +215 -215
  98. data/test/singleton_test.rb +38 -38
  99. data/test/stack_printer_test.rb +77 -78
  100. data/test/stack_test.rb +138 -138
  101. data/test/start_stop_test.rb +112 -112
  102. data/test/test_helper.rb +267 -275
  103. data/test/thread_test.rb +187 -187
  104. data/test/unique_call_path_test.rb +202 -202
  105. data/test/yarv_test.rb +55 -55
  106. metadata +17 -96
  107. data/doc/LICENSE.html +0 -115
  108. data/doc/README_rdoc.html +0 -637
  109. data/doc/Rack.html +0 -96
  110. data/doc/Rack/RubyProf.html +0 -233
  111. data/doc/Rack/RubyProf/RackProfiler.html +0 -343
  112. data/doc/RubyProf.html +0 -974
  113. data/doc/RubyProf/AbstractPrinter.html +0 -625
  114. data/doc/RubyProf/AggregateCallInfo.html +0 -552
  115. data/doc/RubyProf/CallInfo.html +0 -579
  116. data/doc/RubyProf/CallInfoPrinter.html +0 -121
  117. data/doc/RubyProf/CallInfoVisitor.html +0 -199
  118. data/doc/RubyProf/CallStackPrinter.html +0 -1127
  119. data/doc/RubyProf/CallTreePrinter.html +0 -725
  120. data/doc/RubyProf/Cmd.html +0 -637
  121. data/doc/RubyProf/DeprecationWarnings.html +0 -148
  122. data/doc/RubyProf/DotPrinter.html +0 -258
  123. data/doc/RubyProf/FlatPrinter.html +0 -164
  124. data/doc/RubyProf/FlatPrinterWithLineNumbers.html +0 -210
  125. data/doc/RubyProf/GraphHtmlPrinter.html +0 -558
  126. data/doc/RubyProf/GraphPrinter.html +0 -140
  127. data/doc/RubyProf/MethodInfo.html +0 -676
  128. data/doc/RubyProf/MultiPrinter.html +0 -574
  129. data/doc/RubyProf/Profile.html +0 -908
  130. data/doc/RubyProf/Profile/ExcludeCommonMethods.html +0 -411
  131. data/doc/RubyProf/Profile/LegacyMethodElimination.html +0 -158
  132. data/doc/RubyProf/ProfileTask.html +0 -491
  133. data/doc/RubyProf/Thread.html +0 -275
  134. data/doc/created.rid +0 -33
  135. data/doc/css/fonts.css +0 -167
  136. data/doc/css/rdoc.css +0 -590
  137. data/doc/examples/flat_txt.html +0 -139
  138. data/doc/examples/graph_html.html +0 -910
  139. data/doc/examples/graph_txt.html +0 -248
  140. data/doc/fonts/Lato-Light.ttf +0 -0
  141. data/doc/fonts/Lato-LightItalic.ttf +0 -0
  142. data/doc/fonts/Lato-Regular.ttf +0 -0
  143. data/doc/fonts/Lato-RegularItalic.ttf +0 -0
  144. data/doc/fonts/SourceCodePro-Bold.ttf +0 -0
  145. data/doc/fonts/SourceCodePro-Regular.ttf +0 -0
  146. data/doc/images/add.png +0 -0
  147. data/doc/images/arrow_up.png +0 -0
  148. data/doc/images/brick.png +0 -0
  149. data/doc/images/brick_link.png +0 -0
  150. data/doc/images/bug.png +0 -0
  151. data/doc/images/bullet_black.png +0 -0
  152. data/doc/images/bullet_toggle_minus.png +0 -0
  153. data/doc/images/bullet_toggle_plus.png +0 -0
  154. data/doc/images/date.png +0 -0
  155. data/doc/images/delete.png +0 -0
  156. data/doc/images/find.png +0 -0
  157. data/doc/images/loadingAnimation.gif +0 -0
  158. data/doc/images/macFFBgHack.png +0 -0
  159. data/doc/images/package.png +0 -0
  160. data/doc/images/page_green.png +0 -0
  161. data/doc/images/page_white_text.png +0 -0
  162. data/doc/images/page_white_width.png +0 -0
  163. data/doc/images/plugin.png +0 -0
  164. data/doc/images/ruby.png +0 -0
  165. data/doc/images/tag_blue.png +0 -0
  166. data/doc/images/tag_green.png +0 -0
  167. data/doc/images/transparent.png +0 -0
  168. data/doc/images/wrench.png +0 -0
  169. data/doc/images/wrench_orange.png +0 -0
  170. data/doc/images/zoom.png +0 -0
  171. data/doc/index.html +0 -666
  172. data/doc/js/darkfish.js +0 -161
  173. data/doc/js/jquery.js +0 -4
  174. data/doc/js/navigation.js +0 -142
  175. data/doc/js/navigation.js.gz +0 -0
  176. data/doc/js/search.js +0 -109
  177. data/doc/js/search_index.js +0 -1
  178. data/doc/js/search_index.js.gz +0 -0
  179. data/doc/js/searcher.js +0 -229
  180. data/doc/js/searcher.js.gz +0 -0
  181. data/doc/table_of_contents.html +0 -1052
  182. data/examples/cachegrind.out.1 +0 -114
  183. data/examples/cachegrind.out.1.32313213 +0 -114
  184. data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +0 -108
  185. data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +0 -110
@@ -1,70 +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
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
@@ -1,83 +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
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
@@ -1,249 +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
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