ruby-prof 1.7.2 → 2.0.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/{CHANGES → CHANGELOG.md} +112 -178
  3. data/README.md +5 -5
  4. data/bin/ruby-prof +1 -4
  5. data/docs/advanced-usage.md +132 -0
  6. data/docs/alternatives.md +98 -0
  7. data/docs/architecture.md +122 -0
  8. data/docs/best-practices.md +27 -0
  9. data/docs/getting-started.md +130 -0
  10. data/docs/history.md +11 -0
  11. data/docs/index.md +45 -0
  12. data/docs/profiling-rails.md +64 -0
  13. data/docs/public/examples/example.rb +33 -0
  14. data/docs/public/examples/generate_reports.rb +92 -0
  15. data/docs/public/examples/reports/call_info.txt +27 -0
  16. data/docs/public/examples/reports/call_stack.html +835 -0
  17. data/docs/public/examples/reports/callgrind.out +150 -0
  18. data/docs/public/examples/reports/flame_graph.html +408 -0
  19. data/docs/public/examples/reports/flat.txt +45 -0
  20. data/docs/public/examples/reports/graph.dot +129 -0
  21. data/docs/public/examples/reports/graph.html +1319 -0
  22. data/docs/public/examples/reports/graph.txt +100 -0
  23. data/docs/public/examples/reports/graphviz_viewer.html +1 -0
  24. data/docs/public/images/call_stack.png +0 -0
  25. data/docs/public/images/class_diagram.png +0 -0
  26. data/docs/public/images/dot_printer.png +0 -0
  27. data/docs/public/images/flame_graph.png +0 -0
  28. data/docs/public/images/flat.png +0 -0
  29. data/docs/public/images/graph.png +0 -0
  30. data/docs/public/images/graph_html.png +0 -0
  31. data/docs/public/images/ruby-prof-logo.svg +1 -0
  32. data/docs/reports.md +150 -0
  33. data/docs/stylesheets/extra.css +80 -0
  34. data/ext/ruby_prof/rp_allocation.c +0 -15
  35. data/ext/ruby_prof/rp_allocation.h +29 -33
  36. data/ext/ruby_prof/rp_call_tree.c +3 -0
  37. data/ext/ruby_prof/rp_call_tree.h +1 -4
  38. data/ext/ruby_prof/rp_call_trees.h +1 -4
  39. data/ext/ruby_prof/rp_measurement.c +0 -5
  40. data/ext/ruby_prof/rp_measurement.h +49 -53
  41. data/ext/ruby_prof/rp_method.c +3 -0
  42. data/ext/ruby_prof/rp_method.h +1 -4
  43. data/ext/ruby_prof/rp_profile.c +1 -1
  44. data/ext/ruby_prof/rp_profile.h +1 -5
  45. data/ext/ruby_prof/rp_stack.h +50 -53
  46. data/ext/ruby_prof/rp_thread.h +1 -4
  47. data/ext/ruby_prof/ruby_prof.h +1 -4
  48. data/ext/ruby_prof/vc/ruby_prof.vcxproj +7 -8
  49. data/lib/ruby-prof/assets/call_stack_printer.html.erb +746 -711
  50. data/lib/ruby-prof/assets/flame_graph_printer.html.erb +412 -0
  51. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -355
  52. data/lib/ruby-prof/call_tree.rb +57 -57
  53. data/lib/ruby-prof/call_tree_visitor.rb +36 -36
  54. data/lib/ruby-prof/measurement.rb +17 -17
  55. data/lib/ruby-prof/printers/abstract_printer.rb +19 -33
  56. data/lib/ruby-prof/printers/call_info_printer.rb +53 -53
  57. data/lib/ruby-prof/printers/call_stack_printer.rb +168 -180
  58. data/lib/ruby-prof/printers/call_tree_printer.rb +132 -145
  59. data/lib/ruby-prof/printers/dot_printer.rb +177 -132
  60. data/lib/ruby-prof/printers/flame_graph_printer.rb +79 -0
  61. data/lib/ruby-prof/printers/flat_printer.rb +52 -52
  62. data/lib/ruby-prof/printers/graph_html_printer.rb +62 -63
  63. data/lib/ruby-prof/printers/graph_printer.rb +112 -113
  64. data/lib/ruby-prof/printers/multi_printer.rb +134 -127
  65. data/lib/ruby-prof/profile.rb +13 -0
  66. data/lib/ruby-prof/rack.rb +114 -105
  67. data/lib/ruby-prof/task.rb +147 -147
  68. data/lib/ruby-prof/thread.rb +20 -20
  69. data/lib/ruby-prof/version.rb +1 -1
  70. data/lib/ruby-prof.rb +50 -52
  71. data/lib/unprof.rb +10 -10
  72. data/ruby-prof.gemspec +5 -5
  73. data/test/abstract_printer_test.rb +25 -27
  74. data/test/alias_test.rb +203 -117
  75. data/test/call_tree_builder.rb +126 -126
  76. data/test/call_tree_visitor_test.rb +27 -27
  77. data/test/call_trees_test.rb +66 -66
  78. data/test/duplicate_names_test.rb +32 -32
  79. data/test/dynamic_method_test.rb +50 -50
  80. data/test/exceptions_test.rb +24 -24
  81. data/test/exclude_threads_test.rb +48 -48
  82. data/test/fiber_test.rb +72 -72
  83. data/test/inverse_call_tree_test.rb +174 -174
  84. data/test/line_number_test.rb +138 -1
  85. data/test/marshal_test.rb +144 -145
  86. data/test/measure_allocations.rb +26 -26
  87. data/test/measure_allocations_test.rb +340 -1
  88. data/test/measure_process_time_test.rb +3098 -3142
  89. data/test/measure_times.rb +56 -56
  90. data/test/measure_wall_time_test.rb +511 -372
  91. data/test/measurement_test.rb +82 -82
  92. data/test/merge_test.rb +48 -48
  93. data/test/multi_printer_test.rb +52 -66
  94. data/test/no_method_class_test.rb +15 -15
  95. data/test/pause_resume_test.rb +171 -171
  96. data/test/prime.rb +54 -54
  97. data/test/prime_script.rb +5 -5
  98. data/test/printer_call_stack_test.rb +28 -27
  99. data/test/printer_call_tree_test.rb +30 -30
  100. data/test/printer_flame_graph_test.rb +82 -0
  101. data/test/printer_flat_test.rb +99 -99
  102. data/test/printer_graph_html_test.rb +62 -59
  103. data/test/printer_graph_test.rb +42 -40
  104. data/test/printers_test.rb +28 -44
  105. data/test/printing_recursive_graph_test.rb +81 -81
  106. data/test/profile_test.rb +101 -101
  107. data/test/rack_test.rb +103 -93
  108. data/test/recursive_test.rb +139 -139
  109. data/test/scheduler.rb +4 -0
  110. data/test/singleton_test.rb +39 -38
  111. data/test/stack_printer_test.rb +61 -61
  112. data/test/start_stop_test.rb +106 -106
  113. data/test/test_helper.rb +4 -0
  114. data/test/thread_test.rb +29 -29
  115. data/test/unique_call_path_test.rb +123 -123
  116. data/test/yarv_test.rb +56 -56
  117. metadata +53 -11
  118. data/ext/ruby_prof/rp_measure_memory.c +0 -46
  119. data/lib/ruby-prof/compatibility.rb +0 -113
  120. data/test/compatibility_test.rb +0 -49
  121. data/test/measure_memory_test.rb +0 -1193
@@ -1,132 +1,177 @@
1
- # encoding: utf-8
2
-
3
- require 'set'
4
-
5
- module RubyProf
6
- # Generates a graphviz graph in dot format.
7
- #
8
- # To use the dot printer:
9
- #
10
- # result = RubyProf.profile do
11
- # [code to profile]
12
- # end
13
- #
14
- # printer = RubyProf::DotPrinter.new(result)
15
- # printer.print(STDOUT)
16
- #
17
- # You can use either dot viewer such as GraphViz, or the dot command line tool
18
- # to reformat the output into a wide variety of outputs:
19
- #
20
- # dot -Tpng graph.dot > graph.png
21
- #
22
- class DotPrinter < RubyProf::AbstractPrinter
23
- CLASS_COLOR = '"#666666"'
24
- EDGE_COLOR = '"#666666"'
25
-
26
- # Creates the DotPrinter using a RubyProf::Proile.
27
- def initialize(result)
28
- super(result)
29
- @seen_methods = Set.new
30
- end
31
-
32
- # Print a graph report to the provided output.
33
- #
34
- # output - Any IO object, including STDOUT or a file. The default value is
35
- # STDOUT.
36
- #
37
- # options - Hash of print options. See #setup_options
38
- # for more information.
39
- #
40
- # When profiling results that cover a large number of method calls it
41
- # helps to use the :min_percent option, for example:
42
- #
43
- # DotPrinter.new(result).print(STDOUT, :min_percent=>5)
44
- #
45
- def print(output = STDOUT, options = {})
46
- @output = output
47
- setup_options(options)
48
-
49
- puts 'digraph "Profile" {'
50
- #puts "label=\"#{mode_name} >=#{min_percent}%\\nTotal: #{total_time}\";"
51
- puts "labelloc=t;"
52
- puts "labeljust=l;"
53
- print_threads
54
- puts '}'
55
- end
56
-
57
- private
58
-
59
- # Something of a hack, figure out which constant went with the
60
- # RubyProf.measure_mode so that we can display it. Otherwise it's easy to
61
- # forget what measurement was made.
62
- def mode_name
63
- RubyProf.constants.find{|c| RubyProf.const_get(c) == RubyProf.measure_mode}
64
- end
65
-
66
- def print_threads
67
- @result.threads.each do |thread|
68
- puts "subgraph \"Thread #{thread.id}\" {"
69
-
70
- print_thread(thread)
71
- puts "}"
72
-
73
- print_classes(thread)
74
- end
75
- end
76
-
77
- # Determines an ID to use to represent the subject in the Dot file.
78
- def dot_id(subject)
79
- subject.object_id
80
- end
81
-
82
- def print_thread(thread)
83
- total_time = thread.total_time
84
- thread.methods.sort_by(&sort_method).reverse_each do |method|
85
- total_percentage = (method.total_time/total_time) * 100
86
-
87
- next if total_percentage < min_percent
88
- name = method.full_name.split("#").last
89
- puts "#{dot_id(method)} [label=\"#{name}\\n(#{total_percentage.round}%)\"];"
90
- @seen_methods << method
91
- print_edges(total_time, method)
92
- end
93
- end
94
-
95
- def print_classes(thread)
96
- grouped = {}
97
- thread.methods.each{|m| grouped[m.klass_name] ||= []; grouped[m.klass_name] << m}
98
- grouped.each do |cls, methods2|
99
- # Filter down to just seen methods
100
- big_methods = methods2.select{|m| @seen_methods.include? m}
101
-
102
- if !big_methods.empty?
103
- puts "subgraph cluster_#{cls.object_id} {"
104
- puts "label = \"#{cls}\";"
105
- puts "fontcolor = #{CLASS_COLOR};"
106
- puts "fontsize = 16;"
107
- puts "color = #{CLASS_COLOR};"
108
- big_methods.each do |m|
109
- puts "#{m.object_id};"
110
- end
111
- puts "}"
112
- end
113
- end
114
- end
115
-
116
- def print_edges(total_time, method)
117
- method.call_trees.callers.sort_by(&:total_time).reverse.each do |call_tree|
118
- target_percentage = (call_tree.target.total_time / total_time) * 100.0
119
- next if target_percentage < min_percent
120
-
121
- # Get children method
122
- puts "#{dot_id(method)} -> #{dot_id(call_tree.target)} [label=\"#{call_tree.called}/#{call_tree.target.called}\" fontsize=10 fontcolor=#{EDGE_COLOR}];"
123
- end
124
- end
125
-
126
- # Silly little helper for printing to the @output
127
- def puts(str)
128
- @output.puts(str)
129
- end
130
-
131
- end
132
- end
1
+ # encoding: utf-8
2
+
3
+ require 'set'
4
+
5
+ module RubyProf
6
+ # Generates a graphviz graph in dot format.
7
+ #
8
+ # To use the dot printer:
9
+ #
10
+ # result = RubyProf.profile do
11
+ # [code to profile]
12
+ # end
13
+ #
14
+ # printer = RubyProf::DotPrinter.new(result)
15
+ # printer.print(STDOUT)
16
+ #
17
+ # You can use either dot viewer such as GraphViz, or the dot command line tool
18
+ # to reformat the output into a wide variety of outputs:
19
+ #
20
+ # dot -Tpng graph.dot > graph.png
21
+ #
22
+ class DotPrinter < RubyProf::AbstractPrinter
23
+ CLUSTER_COLORS = %w[#1A35A6 #2E86C1 #1ABC9C #5B2C8E #2471A3 #148F77 #1F618D #7D3C98]
24
+
25
+ # Creates the DotPrinter using a RubyProf::Proile.
26
+ def initialize(result)
27
+ super(result)
28
+ @seen_methods = Set.new
29
+ @class_color_map = {}
30
+ @color_index = 0
31
+ end
32
+
33
+ # Print a graph report to the provided output.
34
+ #
35
+ # output - Any IO object, including STDOUT or a file. The default value is
36
+ # STDOUT.
37
+ #
38
+ # Keyword arguments - See AbstractPrinter#print for available options.
39
+ #
40
+ # When profiling results that cover a large number of method calls it
41
+ # helps to use the min_percent: option, for example:
42
+ #
43
+ # DotPrinter.new(result).print(STDOUT, min_percent: 5)
44
+ #
45
+ def print(output = STDOUT, min_percent: 0, max_percent: 100, filter_by: :self_time, sort_method: nil, **)
46
+ @output = output
47
+ @min_percent = min_percent
48
+ @max_percent = max_percent
49
+ @filter_by = filter_by
50
+ @sort_method = sort_method
51
+
52
+ puts 'digraph "Profile" {'
53
+ puts 'rankdir=TB;'
54
+ puts 'bgcolor="#FAFAFA";'
55
+ puts 'node [fontname="Helvetica" fontsize=11 style="filled,rounded" shape=box fillcolor="#FFFFFF" color="#CCCCCC" penwidth=1.2];'
56
+ puts 'edge [fontname="Helvetica" fontsize=9 color="#5B7DB1" arrowsize=0.7];'
57
+ puts 'labelloc=t;'
58
+ puts 'labeljust=l;'
59
+ print_threads
60
+ puts '}'
61
+ end
62
+
63
+ private
64
+
65
+ # Something of a hack, figure out which constant went with the
66
+ # RubyProf.measure_mode so that we can display it. Otherwise it's easy to
67
+ # forget what measurement was made.
68
+ def mode_name
69
+ RubyProf.constants.find{|c| RubyProf.const_get(c) == RubyProf.measure_mode}
70
+ end
71
+
72
+ def print_threads
73
+ @result.threads.each do |thread|
74
+ puts "subgraph \"Thread #{thread.id}\" {"
75
+
76
+ print_thread(thread)
77
+ puts "}"
78
+
79
+ print_classes(thread)
80
+ end
81
+ end
82
+
83
+ # Determines an ID to use to represent the subject in the Dot file.
84
+ def dot_id(subject)
85
+ subject.object_id
86
+ end
87
+
88
+ def color_for_class(klass_name)
89
+ @class_color_map[klass_name] ||= begin
90
+ color = CLUSTER_COLORS[@color_index % CLUSTER_COLORS.length]
91
+ @color_index += 1
92
+ color
93
+ end
94
+ end
95
+
96
+ def node_color(total_percentage)
97
+ if total_percentage >= 50
98
+ '#0D2483'
99
+ elsif total_percentage >= 25
100
+ '#1A35A6'
101
+ elsif total_percentage >= 10
102
+ '#2E86C1'
103
+ elsif total_percentage >= 5
104
+ '#D4E6F1'
105
+ else
106
+ '#FFFFFF'
107
+ end
108
+ end
109
+
110
+ def node_fontcolor(total_percentage)
111
+ total_percentage >= 10 ? '#FFFFFF' : '#333333'
112
+ end
113
+
114
+ def print_thread(thread)
115
+ total_time = thread.total_time
116
+ thread.methods.sort_by(&sort_method).reverse_each do |method|
117
+ total_percentage = (method.total_time/total_time) * 100
118
+
119
+ next if total_percentage < min_percent
120
+ name = method.full_name.split("#").last
121
+ label = "#{name}\\n(#{total_percentage.round}%)"
122
+
123
+ # Only emit fill/font attrs when they differ from the default (white/#333)
124
+ fill = node_color(total_percentage)
125
+ fontcolor = node_fontcolor(total_percentage)
126
+ attrs = "label=\"#{label}\""
127
+ attrs += " fillcolor=\"#{fill}\" fontcolor=\"#{fontcolor}\"" unless fill == '#FFFFFF'
128
+
129
+ puts "#{dot_id(method)} [#{attrs}];"
130
+ @seen_methods << method
131
+ print_edges(total_time, method)
132
+ end
133
+ end
134
+
135
+ def print_classes(thread)
136
+ grouped = {}
137
+ thread.methods.each{|m| grouped[m.klass_name] ||= []; grouped[m.klass_name] << m}
138
+ grouped.each do |cls, methods2|
139
+ # Filter down to just seen methods
140
+ big_methods = methods2.select{|m| @seen_methods.include? m}
141
+
142
+ if !big_methods.empty?
143
+ color = color_for_class(cls)
144
+ puts "subgraph cluster_#{cls.object_id} {"
145
+ puts "label = \"#{cls}\";"
146
+ puts "fontname = \"Helvetica\";"
147
+ puts "fontcolor = \"#{color}\";"
148
+ puts "fontsize = 14;"
149
+ puts "color = \"#{color}\";"
150
+ puts "style = \"rounded,dashed\";"
151
+ puts "penwidth = 1.5;"
152
+ big_methods.each do |m|
153
+ puts "#{m.object_id};"
154
+ end
155
+ puts "}"
156
+ end
157
+ end
158
+ end
159
+
160
+ def print_edges(total_time, method)
161
+ method.call_trees.callees.sort_by(&:total_time).reverse.each do |call_tree|
162
+ target_percentage = (call_tree.target.total_time / total_time) * 100.0
163
+ next if target_percentage < min_percent
164
+ next unless @seen_methods.include?(call_tree.target)
165
+
166
+ edge_width = [0.5 + (target_percentage / 20.0), 4.0].min
167
+ puts "#{dot_id(method)} -> #{dot_id(call_tree.target)} [label=\"#{call_tree.called}/#{call_tree.target.called}\" penwidth=#{format('%.1f', edge_width)}];"
168
+ end
169
+ end
170
+
171
+ # Silly little helper for printing to the @output
172
+ def puts(str)
173
+ @output.puts(str)
174
+ end
175
+
176
+ end
177
+ end
@@ -0,0 +1,79 @@
1
+ # encoding: utf-8
2
+
3
+ require 'erb'
4
+ require 'json'
5
+
6
+ module RubyProf
7
+ # Prints a HTML flame graph visualization of the call tree.
8
+ #
9
+ # To use the printer:
10
+ #
11
+ # result = RubyProf.profile do
12
+ # [code to profile]
13
+ # end
14
+ #
15
+ # printer = RubyProf::FlameGraphPrinter.new(result)
16
+ # printer.print(STDOUT)
17
+
18
+ class FlameGraphPrinter < AbstractPrinter
19
+ include ERB::Util
20
+
21
+ # Specify print options.
22
+ #
23
+ # output - Any IO object, including STDOUT or a file.
24
+ #
25
+ # Keyword arguments:
26
+ # title: - a String to override the default "ruby-prof flame graph"
27
+ # title of the report.
28
+ #
29
+ # Also accepts min_percent:, max_percent:, filter_by:, and sort_method:
30
+ # from AbstractPrinter.
31
+ def print(output = STDOUT, title: "ruby-prof flame graph",
32
+ min_percent: 0, max_percent: 100, filter_by: :self_time, sort_method: nil, **)
33
+ @min_percent = min_percent
34
+ @max_percent = max_percent
35
+ @filter_by = filter_by
36
+ @sort_method = sort_method
37
+ @title = title
38
+ output << ERB.new(self.template).result(binding)
39
+ end
40
+
41
+ attr_reader :title
42
+
43
+ def build_flame_data(call_tree, visited = Set.new)
44
+ node = {
45
+ name: call_tree.target.full_name,
46
+ value: call_tree.total_time,
47
+ self_value: call_tree.self_time,
48
+ called: call_tree.called,
49
+ children: []
50
+ }
51
+
52
+ unless visited.include?(call_tree.target)
53
+ visited.add(call_tree.target)
54
+ call_tree.children.sort_by { |c| -c.total_time }.each do |child|
55
+ node[:children] << build_flame_data(child, visited)
56
+ end
57
+ visited.delete(call_tree.target)
58
+ end
59
+
60
+ node
61
+ end
62
+
63
+ def flame_data_json
64
+ threads = @result.threads.map do |thread|
65
+ {
66
+ id: thread.id,
67
+ fiber_id: thread.fiber_id,
68
+ total_time: thread.total_time,
69
+ data: build_flame_data(thread.call_tree)
70
+ }
71
+ end
72
+ JSON.generate(threads)
73
+ end
74
+
75
+ def template
76
+ open_asset('flame_graph_printer.html.erb')
77
+ end
78
+ end
79
+ end
@@ -1,53 +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_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
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 to default sort by self time
16
+ def print(output = STDOUT, sort_method: :self_time, **options)
17
+ super(output, sort_method: sort_method, **options)
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
53
  end
@@ -1,63 +1,62 @@
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_percent
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
+ # 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
+ class GraphHtmlPrinter < AbstractPrinter
17
+ include ERB::Util
18
+
19
+ def print(output = STDOUT, min_time: nil, nonzero: false,
20
+ min_percent: 0, max_percent: 100, filter_by: :self_time, sort_method: nil, **)
21
+ @min_percent = min_percent
22
+ @max_percent = max_percent
23
+ @filter_by = filter_by
24
+ @sort_method = sort_method
25
+ @min_time = min_time
26
+ @nonzero = nonzero
27
+ output << ERB.new(self.template).result(binding)
28
+ end
29
+
30
+ # Creates a link to a method. Note that we do not create
31
+ # links to methods which are under the min_percent
32
+ # specified by the user, since they will not be
33
+ # printed out.
34
+ def create_link(thread, overall_time, method)
35
+ total_percent = (method.total_time/overall_time) * 100
36
+ if total_percent < min_percent
37
+ # Just return name
38
+ h method.full_name
39
+ else
40
+ href = '#' + method_href(thread, method)
41
+ "<a href=\"#{href}\">#{h method.full_name}</a>"
42
+ end
43
+ end
44
+
45
+ def method_href(thread, method)
46
+ h(method.full_name.gsub(/[><#\.\?=:]/,"_") + "_" + thread.fiber_id.to_s)
47
+ end
48
+
49
+ def file_link(path, linenum)
50
+ if path.nil?
51
+ ""
52
+ else
53
+ srcfile = File.expand_path(path)
54
+ "<a href=\"file://#{h srcfile}##{linenum}\" title=\"#{h srcfile}:#{linenum}\">#{linenum}</a>"
55
+ end
56
+ end
57
+
58
+ def template
59
+ open_asset('graph_printer.html.erb')
60
+ end
61
+ end
62
+ end