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,57 +1,57 @@
1
- # encoding: utf-8
2
-
3
- module RubyProf
4
- # The CallTree class is used to track the relationships between methods. It is a helper class used by
5
- # RubyProf::MethodInfo to keep track of which methods called a given method and which methods a given
6
- # method called. Each CallTree has a parent and target method. You cannot create a CallTree object directly,
7
- # they are generated while running a profile.
8
- class CallTree
9
- # The number of times the parent method called the target method
10
- def called
11
- self.measurement.called
12
- end
13
-
14
- # The total time resulting from the parent method calling the target method
15
- def total_time
16
- self.measurement.total_time
17
- end
18
-
19
- # The self time (of the parent) resulting from the parent method calling the target method
20
- def self_time
21
- self.measurement.self_time
22
- end
23
-
24
- # The wait time (of the parent) resulting from the parent method calling the target method
25
- def wait_time
26
- self.measurement.wait_time
27
- end
28
-
29
- # The time spent in child methods resulting from the parent method calling the target method
30
- def children_time
31
- self.total_time - self.self_time - self.wait_time
32
- end
33
-
34
- # Compares two CallTree instances. The comparison is based on the CallTree#parent, CallTree#target,
35
- # and total time.
36
- def <=>(other)
37
- if self.target == other.target && self.parent == other.parent
38
- 0
39
- elsif self.total_time < other.total_time
40
- -1
41
- elsif self.total_time > other.total_time
42
- 1
43
- else
44
- self.target.full_name <=> other.target.full_name
45
- end
46
- end
47
-
48
- # :nodoc:
49
- def to_s
50
- "<#{self.class.name} - #{self.target.full_name}>"
51
- end
52
-
53
- def inspect
54
- self.to_s
55
- end
56
- end
57
- end
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ # The CallTree class is used to track the relationships between methods. It is a helper class used by
5
+ # RubyProf::MethodInfo to keep track of which methods called a given method and which methods a given
6
+ # method called. Each CallTree has a parent and target method. You cannot create a CallTree object directly,
7
+ # they are generated while running a profile.
8
+ class CallTree
9
+ # The number of times the parent method called the target method
10
+ def called
11
+ self.measurement.called
12
+ end
13
+
14
+ # The total time resulting from the parent method calling the target method
15
+ def total_time
16
+ self.measurement.total_time
17
+ end
18
+
19
+ # The self time (of the parent) resulting from the parent method calling the target method
20
+ def self_time
21
+ self.measurement.self_time
22
+ end
23
+
24
+ # The wait time (of the parent) resulting from the parent method calling the target method
25
+ def wait_time
26
+ self.measurement.wait_time
27
+ end
28
+
29
+ # The time spent in child methods resulting from the parent method calling the target method
30
+ def children_time
31
+ self.total_time - self.self_time - self.wait_time
32
+ end
33
+
34
+ # Compares two CallTree instances. The comparison is based on the CallTree#parent, CallTree#target,
35
+ # and total time.
36
+ def <=>(other)
37
+ if self.target == other.target && self.parent == other.parent
38
+ 0
39
+ elsif self.total_time < other.total_time
40
+ -1
41
+ elsif self.total_time > other.total_time
42
+ 1
43
+ else
44
+ self.target.full_name <=> other.target.full_name
45
+ end
46
+ end
47
+
48
+ # :nodoc:
49
+ def to_s
50
+ "<#{self.class.name} - #{self.target.full_name}>"
51
+ end
52
+
53
+ def inspect
54
+ self.to_s
55
+ end
56
+ end
57
+ end
@@ -1,36 +1,36 @@
1
- module RubyProf
2
- # The call info visitor class does a depth-first traversal across a
3
- # list of call infos. At each call_tree node, the visitor executes
4
- # the block provided in the #visit method. The block is passed two
5
- # parameters, the event and the call_tree instance. Event will be
6
- # either :enter or :exit.
7
- #
8
- # visitor = RubyProf::CallTreeVisitor.new(result.threads.first.call_tree)
9
- #
10
- # method_names = Array.new
11
- #
12
- # visitor.visit do |call_tree, event|
13
- # method_names << call_tree.target.full_name if event == :enter
14
- # end
15
- #
16
- # puts method_names
17
- class CallTreeVisitor
18
- def initialize(call_tree)
19
- @call_tree = call_tree
20
- end
21
-
22
- def visit(&block)
23
- visit_call_tree(@call_tree, &block)
24
- end
25
-
26
- private
27
-
28
- def visit_call_tree(call_tree, &block)
29
- yield call_tree, :enter
30
- call_tree.children.each do |child|
31
- visit_call_tree(child, &block)
32
- end
33
- yield call_tree, :exit
34
- end
35
- end
36
- end
1
+ module RubyProf
2
+ # The call info visitor class does a depth-first traversal across a
3
+ # list of call infos. At each call_tree node, the visitor executes
4
+ # the block provided in the #visit method. The block is passed two
5
+ # parameters, the event and the call_tree instance. Event will be
6
+ # either :enter or :exit.
7
+ #
8
+ # visitor = RubyProf::CallTreeVisitor.new(result.threads.first.call_tree)
9
+ #
10
+ # method_names = Array.new
11
+ #
12
+ # visitor.visit do |call_tree, event|
13
+ # method_names << call_tree.target.full_name if event == :enter
14
+ # end
15
+ #
16
+ # puts method_names
17
+ class CallTreeVisitor
18
+ def initialize(call_tree)
19
+ @call_tree = call_tree
20
+ end
21
+
22
+ def visit(&block)
23
+ visit_call_tree(@call_tree, &block)
24
+ end
25
+
26
+ private
27
+
28
+ def visit_call_tree(call_tree, &block)
29
+ yield call_tree, :enter
30
+ call_tree.children.each do |child|
31
+ visit_call_tree(child, &block)
32
+ end
33
+ yield call_tree, :exit
34
+ end
35
+ end
36
+ end
@@ -1,17 +1,17 @@
1
- module RubyProf
2
- # The Measurement class is a helper class used by RubyProf::MethodInfo to store information about the method.
3
- # You cannot create a CallTree object directly, they are generated while running a profile.
4
- class Measurement
5
- def children_time
6
- self.total_time - self.self_time - self.wait_time
7
- end
8
-
9
- def to_s
10
- "c: #{called}, tt: #{total_time}, st: #{self_time}"
11
- end
12
-
13
- def inspect
14
- super + "(#{self.to_s})"
15
- end
16
- end
17
- end
1
+ module RubyProf
2
+ # The Measurement class is a helper class used by RubyProf::MethodInfo to store information about the method.
3
+ # You cannot create a CallTree object directly, they are generated while running a profile.
4
+ class Measurement
5
+ def children_time
6
+ self.total_time - self.self_time - self.wait_time
7
+ end
8
+
9
+ def to_s
10
+ "c: #{called}, tt: #{total_time}, st: #{self_time}"
11
+ end
12
+
13
+ def inspect
14
+ super + "(#{self.to_s})"
15
+ end
16
+ end
17
+ end
@@ -17,60 +17,46 @@ module RubyProf
17
17
  @output = nil
18
18
  end
19
19
 
20
- # Returns the min_percent of time a method must take to be included in a profiling report
21
- def min_percent
22
- @options[:min_percent] || 0
23
- end
24
-
25
- # Returns the max_percent of time a method can take to be included in a profiling report
26
- def max_percent
27
- @options[:max_percent] || 100
28
- end
29
-
30
- # Returns the method to filter methods by (when using min_percent and max_percent)
31
- def filter_by
32
- @options[:filter_by] || :self_time
33
- end
20
+ attr_reader :min_percent, :max_percent, :filter_by, :sort_method
34
21
 
35
22
  # Returns the time format used to show when a profile was run
36
23
  def time_format
37
24
  '%A, %B %-d at %l:%M:%S %p (%Z)'
38
25
  end
39
26
 
40
- # Returns how profile data should be sorted
41
- def sort_method
42
- @options[:sort_method]
43
- end
44
-
45
27
  # Prints a report to the provided output.
46
28
  #
47
29
  # output - Any IO object, including STDOUT or a file.
48
30
  # The default value is STDOUT.
49
31
  #
50
- # options - Hash of print options. Note that each printer can
51
- # define its own set of options.
52
- #
53
- # :min_percent - Number 0 to 100 that specifies the minimum
32
+ # Keyword arguments:
33
+ # min_percent - Number 0 to 100 that specifies the minimum
54
34
  # %self (the methods self time divided by the
55
35
  # overall total time) that a method must take
56
36
  # for it to be printed out in the report.
57
37
  # Default value is 0.
58
38
  #
59
- # :sort_method - Specifies method used for sorting method infos.
39
+ # max_percent - Number 0 to 100 that specifies the maximum
40
+ # %self for methods to include.
41
+ # Default value is 100.
42
+ #
43
+ # filter_by - Which time metric to use when applying
44
+ # min_percent and max_percent filters.
45
+ # Default value is :self_time.
46
+ #
47
+ # sort_method - Specifies method used for sorting method infos.
60
48
  # Available values are :total_time, :self_time,
61
- # :wait_time, :children_time
62
- # Default value is :total_time
63
- def print(output = STDOUT, options = {})
49
+ # :wait_time, :children_time.
50
+ # Default value depends on the printer.
51
+ def print(output = STDOUT, min_percent: 0, max_percent: 100, filter_by: :self_time, sort_method: nil, **)
64
52
  @output = output
65
- setup_options(options)
53
+ @min_percent = min_percent
54
+ @max_percent = max_percent
55
+ @filter_by = filter_by
56
+ @sort_method = sort_method
66
57
  print_threads
67
58
  end
68
59
 
69
- # :nodoc:
70
- def setup_options(options = {})
71
- @options = options
72
- end
73
-
74
60
  def method_location(method)
75
61
  if method.source_file
76
62
  "#{method.source_file}:#{method.line}"
@@ -1,53 +1,53 @@
1
- # encoding: utf-8
2
-
3
- module RubyProf
4
- # Prints out the call graph based on CallTree instances. This
5
- # is mainly for debugging purposes as it provides access into
6
- # into RubyProf's internals.
7
- #
8
- # To use the printer:
9
- #
10
- # result = RubyProf.profile do
11
- # [code to profile]
12
- # end
13
- #
14
- # printer = RubyProf::CallInfoPrinter.new(result)
15
- # printer.print(STDOUT)
16
- class CallInfoPrinter < AbstractPrinter
17
- TIME_WIDTH = 0
18
-
19
- private
20
-
21
- def print_header(thread)
22
- @output << "----------------------------------------------------\n"
23
- @output << "Thread ID: #{thread.id}\n"
24
- @output << "Fiber ID: #{thread.fiber_id}\n"
25
- @output << "Total Time: #{thread.total_time}\n"
26
- @output << "Sort by: #{sort_method}\n"
27
- @output << "\n"
28
- end
29
-
30
- def print_methods(thread)
31
- visitor = CallTreeVisitor.new(thread.call_tree)
32
-
33
- visitor.visit do |call_tree, event|
34
- if event == :enter
35
- @output << " " * call_tree.depth
36
- @output << call_tree.target.full_name
37
- @output << " ("
38
- @output << "tt:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.total_time)}, "
39
- @output << "st:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.self_time)}, "
40
- @output << "wt:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.wait_time)}, "
41
- @output << "ct:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.children_time)}, "
42
- @output << "call:#{call_tree.called}, "
43
- @output << ")"
44
- @output << "\n"
45
- end
46
- end
47
- end
48
-
49
- def print_footer(thread)
50
- @output << "\n" << "\n"
51
- end
52
- end
53
- end
1
+ # encoding: utf-8
2
+
3
+ module RubyProf
4
+ # Prints out the call graph based on CallTree instances. This
5
+ # is mainly for debugging purposes as it provides access into
6
+ # into RubyProf's internals.
7
+ #
8
+ # To use the printer:
9
+ #
10
+ # result = RubyProf.profile do
11
+ # [code to profile]
12
+ # end
13
+ #
14
+ # printer = RubyProf::CallInfoPrinter.new(result)
15
+ # printer.print(STDOUT)
16
+ class CallInfoPrinter < AbstractPrinter
17
+ TIME_WIDTH = 0
18
+
19
+ private
20
+
21
+ def print_header(thread)
22
+ @output << "----------------------------------------------------\n"
23
+ @output << "Thread ID: #{thread.id}\n"
24
+ @output << "Fiber ID: #{thread.fiber_id}\n"
25
+ @output << "Total Time: #{thread.total_time}\n"
26
+ @output << "Sort by: #{sort_method}\n"
27
+ @output << "\n"
28
+ end
29
+
30
+ def print_methods(thread)
31
+ visitor = CallTreeVisitor.new(thread.call_tree)
32
+
33
+ visitor.visit do |call_tree, event|
34
+ if event == :enter
35
+ @output << " " * call_tree.depth
36
+ @output << call_tree.target.full_name
37
+ @output << " ("
38
+ @output << "tt:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.total_time)}, "
39
+ @output << "st:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.self_time)}, "
40
+ @output << "wt:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.wait_time)}, "
41
+ @output << "ct:#{sprintf("%#{TIME_WIDTH}.2f", call_tree.children_time)}, "
42
+ @output << "call:#{call_tree.called}, "
43
+ @output << ")"
44
+ @output << "\n"
45
+ end
46
+ end
47
+ end
48
+
49
+ def print_footer(thread)
50
+ @output << "\n" << "\n"
51
+ end
52
+ end
53
+ end