ruby-prof 0.18.0 → 1.2.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 (129) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +44 -1
  3. data/LICENSE +2 -2
  4. data/README.rdoc +1 -483
  5. data/Rakefile +3 -6
  6. data/bin/ruby-prof +111 -128
  7. data/ext/ruby_prof/extconf.rb +6 -38
  8. data/ext/ruby_prof/rp_aggregate_call_tree.c +41 -0
  9. data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
  10. data/ext/ruby_prof/rp_allocation.c +259 -0
  11. data/ext/ruby_prof/rp_allocation.h +31 -0
  12. data/ext/ruby_prof/rp_call_tree.c +353 -0
  13. data/ext/ruby_prof/rp_call_tree.h +43 -0
  14. data/ext/ruby_prof/rp_call_trees.c +266 -0
  15. data/ext/ruby_prof/rp_call_trees.h +29 -0
  16. data/ext/ruby_prof/rp_measure_allocations.c +25 -51
  17. data/ext/ruby_prof/rp_measure_memory.c +21 -56
  18. data/ext/ruby_prof/rp_measure_process_time.c +37 -43
  19. data/ext/ruby_prof/rp_measure_wall_time.c +40 -21
  20. data/ext/ruby_prof/rp_measurement.c +221 -0
  21. data/ext/ruby_prof/rp_measurement.h +50 -0
  22. data/ext/ruby_prof/rp_method.c +279 -439
  23. data/ext/ruby_prof/rp_method.h +33 -45
  24. data/ext/ruby_prof/rp_profile.c +902 -0
  25. data/ext/ruby_prof/rp_profile.h +36 -0
  26. data/ext/ruby_prof/rp_stack.c +163 -132
  27. data/ext/ruby_prof/rp_stack.h +18 -28
  28. data/ext/ruby_prof/rp_thread.c +192 -124
  29. data/ext/ruby_prof/rp_thread.h +18 -8
  30. data/ext/ruby_prof/ruby_prof.c +36 -778
  31. data/ext/ruby_prof/ruby_prof.h +11 -45
  32. data/ext/ruby_prof/vc/ruby_prof.vcxproj +18 -12
  33. data/lib/ruby-prof.rb +4 -21
  34. data/lib/ruby-prof/assets/call_stack_printer.html.erb +710 -0
  35. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  36. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -0
  37. data/lib/ruby-prof/call_tree.rb +57 -0
  38. data/lib/ruby-prof/call_tree_visitor.rb +36 -0
  39. data/lib/ruby-prof/compatibility.rb +37 -107
  40. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  41. data/lib/ruby-prof/measurement.rb +17 -0
  42. data/lib/ruby-prof/method_info.rb +47 -90
  43. data/lib/ruby-prof/printers/abstract_printer.rb +73 -50
  44. data/lib/ruby-prof/printers/call_info_printer.rb +24 -12
  45. data/lib/ruby-prof/printers/call_stack_printer.rb +66 -152
  46. data/lib/ruby-prof/printers/call_tree_printer.rb +20 -12
  47. data/lib/ruby-prof/printers/dot_printer.rb +5 -5
  48. data/lib/ruby-prof/printers/flat_printer.rb +6 -24
  49. data/lib/ruby-prof/printers/graph_html_printer.rb +6 -192
  50. data/lib/ruby-prof/printers/graph_printer.rb +11 -14
  51. data/lib/ruby-prof/printers/multi_printer.rb +66 -23
  52. data/lib/ruby-prof/profile.rb +10 -3
  53. data/lib/ruby-prof/thread.rb +5 -20
  54. data/lib/ruby-prof/version.rb +1 -1
  55. data/ruby-prof.gemspec +9 -2
  56. data/test/abstract_printer_test.rb +0 -27
  57. data/test/alias_test.rb +126 -0
  58. data/test/basic_test.rb +1 -86
  59. data/test/call_tree_visitor_test.rb +32 -0
  60. data/test/call_trees_test.rb +66 -0
  61. data/test/dynamic_method_test.rb +0 -2
  62. data/test/exclude_methods_test.rb +17 -12
  63. data/test/fiber_test.rb +214 -23
  64. data/test/gc_test.rb +105 -0
  65. data/test/inverse_call_tree_test.rb +175 -0
  66. data/test/line_number_test.rb +118 -40
  67. data/test/marshal_test.rb +115 -0
  68. data/test/measure_allocations.rb +30 -0
  69. data/test/measure_allocations_test.rb +361 -12
  70. data/test/measure_allocations_trace_test.rb +375 -0
  71. data/test/measure_memory_trace_test.rb +1101 -0
  72. data/test/measure_process_time_test.rb +757 -33
  73. data/test/measure_times.rb +56 -0
  74. data/test/measure_wall_time_test.rb +329 -149
  75. data/test/multi_printer_test.rb +1 -34
  76. data/test/pause_resume_test.rb +24 -15
  77. data/test/prime.rb +1 -1
  78. data/test/prime_script.rb +6 -0
  79. data/test/printer_call_stack_test.rb +28 -0
  80. data/test/printer_call_tree_test.rb +31 -0
  81. data/test/printer_flat_test.rb +68 -0
  82. data/test/printer_graph_html_test.rb +60 -0
  83. data/test/printer_graph_test.rb +41 -0
  84. data/test/printers_test.rb +32 -166
  85. data/test/printing_recursive_graph_test.rb +26 -72
  86. data/test/recursive_test.rb +68 -77
  87. data/test/stack_printer_test.rb +2 -15
  88. data/test/start_stop_test.rb +22 -25
  89. data/test/test_helper.rb +6 -261
  90. data/test/thread_test.rb +11 -54
  91. data/test/unique_call_path_test.rb +25 -107
  92. data/test/yarv_test.rb +1 -0
  93. metadata +43 -41
  94. data/examples/flat.txt +0 -50
  95. data/examples/graph.dot +0 -84
  96. data/examples/graph.html +0 -823
  97. data/examples/graph.txt +0 -139
  98. data/examples/multi.flat.txt +0 -23
  99. data/examples/multi.graph.html +0 -760
  100. data/examples/multi.grind.dat +0 -114
  101. data/examples/multi.stack.html +0 -547
  102. data/examples/stack.html +0 -547
  103. data/ext/ruby_prof/rp_call_info.c +0 -425
  104. data/ext/ruby_prof/rp_call_info.h +0 -53
  105. data/ext/ruby_prof/rp_measure.c +0 -40
  106. data/ext/ruby_prof/rp_measure.h +0 -45
  107. data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
  108. data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
  109. data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
  110. data/lib/ruby-prof/aggregate_call_info.rb +0 -76
  111. data/lib/ruby-prof/assets/call_stack_printer.css.html +0 -117
  112. data/lib/ruby-prof/assets/call_stack_printer.js.html +0 -385
  113. data/lib/ruby-prof/call_info.rb +0 -115
  114. data/lib/ruby-prof/call_info_visitor.rb +0 -40
  115. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -83
  116. data/lib/ruby-prof/profile/exclude_common_methods.rb +0 -207
  117. data/lib/ruby-prof/profile/legacy_method_elimination.rb +0 -50
  118. data/test/aggregate_test.rb +0 -136
  119. data/test/block_test.rb +0 -74
  120. data/test/call_info_test.rb +0 -78
  121. data/test/call_info_visitor_test.rb +0 -31
  122. data/test/issue137_test.rb +0 -63
  123. data/test/measure_cpu_time_test.rb +0 -212
  124. data/test/measure_gc_runs_test.rb +0 -32
  125. data/test/measure_gc_time_test.rb +0 -36
  126. data/test/measure_memory_test.rb +0 -33
  127. data/test/method_elimination_test.rb +0 -84
  128. data/test/module_test.rb +0 -45
  129. data/test/stack_test.rb +0 -138
@@ -1,53 +1,16 @@
1
1
  # encoding: utf-8
2
2
 
3
- # These methods are here for backwards compatability with previous RubyProf releases
3
+ # These methods are deprecated and are available for backwards compatability.
4
4
  module RubyProf
5
- # Measurements
6
- def self.cpu_frequency
7
- Measure::CpuTime.frequency
8
- end
9
-
10
- def self.measure_allocations
11
- Measure::Allocations.measure
12
- end
13
-
14
- def self.measure_cpu_time
15
- Measure::CpuTime.measure
16
- end
17
-
18
- def self.measure_gc_runs
19
- Measure::GcRuns.measure
20
- end
21
-
22
- def self.measure_gc_time
23
- Measure::GcTime.measure
24
- end
25
-
26
- def self.measure_memory
27
- Measure::Memory.measure
28
- end
29
-
30
- def self.measure_process_time
31
- Measure::ProcessTime.measure
32
- end
33
-
34
- def self.measure_wall_time
35
- Measure::WallTime.measure
36
- end
37
-
38
5
  # call-seq:
39
6
  # measure_mode -> measure_mode
40
7
  #
41
8
  # Returns what ruby-prof is measuring. Valid values include:
42
9
  #
43
- # *RubyProf::WALL_TIME - Measure wall time using gettimeofday on Linx and GetLocalTime on Windows. This is default.
44
- # *RubyProf::PROCESS_TIME - Measure process time. It is implemented using the clock functions in the C Runtime library.
45
- # *RubyProf::CPU_TIME - Measure time using the CPU clock counter. This mode is only supported on Pentium or PowerPC platforms.
46
- # *RubyProf::ALLOCATIONS - Measure object allocations. This requires a patched Ruby interpreter.
47
- # *RubyProf::MEMORY - Measure memory size. This requires a patched Ruby interpreter.
48
- # *RubyProf::GC_RUNS - Measure number of garbage collections. This requires a patched Ruby interpreter.
49
- # *RubyProf::GC_TIME - Measure time spent doing garbage collection. This requires a patched Ruby interpreter.*/
50
-
10
+ # * RubyProf::WALL_TIME
11
+ # * RubyProf::PROCESS_TIME
12
+ # * RubyProf::ALLOCATIONS
13
+ # * RubyProf::MEMORY
51
14
  def self.measure_mode
52
15
  @measure_mode ||= RubyProf::WALL_TIME
53
16
  end
@@ -57,66 +20,38 @@ module RubyProf
57
20
  #
58
21
  # Specifies what ruby-prof should measure. Valid values include:
59
22
  #
60
- # *RubyProf::WALL_TIME - Measure wall time using gettimeofday on Linx and GetLocalTime on Windows. This is default.
61
- # *RubyProf::PROCESS_TIME - Measure process time. It is implemented using the clock functions in the C Runtime library.
62
- # *RubyProf::CPU_TIME - Measure time using the CPU clock counter. This mode is only supported on Pentium or PowerPC platforms.
63
- # *RubyProf::ALLOCATIONS - Measure object allocations. This requires a patched Ruby interpreter.
64
- # *RubyProf::MEMORY - Measure memory size. This requires a patched Ruby interpreter.
65
- # *RubyProf::GC_RUNS - Measure number of garbage collections. This requires a patched Ruby interpreter.
66
- # *RubyProf::GC_TIME - Measure time spent doing garbage collection. This requires a patched Ruby interpreter.*/
23
+ # * RubyProf::WALL_TIME - Wall time measures the real-world time elapsed between any two moments. If there are other processes concurrently running on the system that use significant CPU or disk time during a profiling run then the reported results will be larger than expected. On Windows, wall time is measured using GetTickCount(), on MacOS by mach_absolute_time, on Linux by clock_gettime and otherwise by gettimeofday.
24
+ # * RubyProf::PROCESS_TIME - Process time measures the time used by a process between any two moments. It is unaffected by other processes concurrently running on the system. Remember with process time that calls to methods like sleep will not be included in profiling results. On Windows, process time is measured using GetProcessTimes and on other platforms by clock_gettime.
25
+ # * RubyProf::ALLOCATIONS - Object allocations measures show how many objects each method in a program allocates. Measurements are done via Ruby's GC.stat api.
26
+ # * RubyProf::MEMORY - Memory measures how much memory each method in a program uses. Measurements are done via Ruby's TracePoint api.
67
27
  def self.measure_mode=(value)
68
28
  @measure_mode = value
69
29
  end
70
30
 
71
- def self.measure_mode_string
72
- case measure_mode
73
- when WALL_TIME then "wall_time"
74
- when CPU_TIME then "cpu_time"
75
- when PROCESS_TIME then "process_time_time"
76
- when ALLOCATIONS then "allocations"
77
- when MEMORY then "memory"
78
- when GC_TIME then "gc_time"
79
- when GC_RUNS then "gc_runs"
80
- end
81
- end
82
-
83
- # call-seq:
84
- # exclude_threads -> exclude_threads
85
- #
86
- # Returns threads ruby-prof should exclude from profiling
87
-
31
+ # Returns the threads that ruby-prof should exclude from profiling
88
32
  def self.exclude_threads
89
33
  @exclude_threads ||= Array.new
90
34
  end
91
35
 
92
- # call-seq:
93
- # exclude_threads= -> void
94
- #
95
- # Specifies what threads ruby-prof should exclude from profiling
96
-
36
+ # Specifies which threads ruby-prof should exclude from profiling
97
37
  def self.exclude_threads=(value)
98
38
  @exclude_threads = value
99
39
  end
100
40
 
101
- # Profiling
102
- def self.start_script(script)
103
- start
104
- load script
105
- end
106
-
41
+ # Starts profiling
107
42
  def self.start
108
43
  ensure_not_running!
109
- @profile = Profile.new(measure_mode: measure_mode, exclude_threads: exclude_threads)
110
- enable_gc_stats_if_needed
44
+ @profile = Profile.new(:measure_mode => measure_mode, :exclude_threads => exclude_threads)
111
45
  @profile.start
112
46
  end
113
47
 
48
+ # Pauses profiling
114
49
  def self.pause
115
50
  ensure_running!
116
- disable_gc_stats_if_needed
117
51
  @profile.pause
118
52
  end
119
53
 
54
+ # Is a profile running?
120
55
  def self.running?
121
56
  if defined?(@profile) and @profile
122
57
  @profile.running?
@@ -125,55 +60,50 @@ module RubyProf
125
60
  end
126
61
  end
127
62
 
63
+ # Resume profiling
128
64
  def self.resume
129
65
  ensure_running!
130
- enable_gc_stats_if_needed
131
66
  @profile.resume
132
67
  end
133
68
 
69
+ # Stops profiling
134
70
  def self.stop
135
71
  ensure_running!
136
72
  result = @profile.stop
137
- disable_gc_stats_if_needed
138
73
  @profile = nil
139
74
  result
140
75
  end
141
76
 
142
- # Profile a block
77
+ # Profiles a block
143
78
  def self.profile(options = {}, &block)
144
79
  ensure_not_running!
145
- gc_stat_was_enabled = enable_gc_stats_if_needed
146
- options = { measure_mode: measure_mode, exclude_threads: exclude_threads }.merge!(options)
147
- result = Profile.profile(options, &block)
148
- ensure
149
- disable_gc_stats_if_needed(gc_stat_was_enabled)
150
- result
80
+ options = {:measure_mode => measure_mode, :exclude_threads => exclude_threads }.merge!(options)
81
+ Profile.profile(options, &block)
151
82
  end
152
83
 
153
-
154
- private
155
- def self.ensure_running!
156
- raise(RuntimeError, "RubyProf.start was not yet called") unless running?
84
+ # :nodoc:
85
+ def self.measure_mode_string
86
+ case measure_mode
87
+ when WALL_TIME then "wall_time"
88
+ when PROCESS_TIME then "process_time"
89
+ when ALLOCATIONS then "allocations"
90
+ when MEMORY then "memory"
91
+ end
157
92
  end
158
93
 
159
- def self.ensure_not_running!
160
- raise(RuntimeError, "RubyProf is already running") if running?
94
+ # :nodoc:
95
+ def self.start_script(script)
96
+ start
97
+ load script
161
98
  end
162
99
 
163
- # for GC.allocated_size to work GC statistics should be enabled
164
- def self.enable_gc_stats_if_needed
165
- if measure_mode_requires_gc_stats_enabled?
166
- @gc_stat_was_enabled = GC.enable_stats
167
- end
168
- end
100
+ private
169
101
 
170
- def self.disable_gc_stats_if_needed(was_enabled=nil)
171
- was_enabled ||= defined?(@gc_stat_was_enabled) && @gc_stat_was_enabled
172
- GC.disable_stats if measure_mode_requires_gc_stats_enabled? && !was_enabled
102
+ def self.ensure_running!
103
+ raise(RuntimeError, "RubyProf.start was not yet called") unless running?
173
104
  end
174
105
 
175
- def self.measure_mode_requires_gc_stats_enabled?
176
- GC.respond_to?(:enable_stats) &&
177
- [RubyProf::MEMORY, RubyProf::GC_TIME, RubyProf::GC_RUNS].include?(measure_mode)
106
+ def self.ensure_not_running!
107
+ raise(RuntimeError, "RubyProf is already running") if running?
178
108
  end
179
109
  end
@@ -0,0 +1,198 @@
1
+ require 'set'
2
+
3
+ # :enddoc:
4
+ module RubyProf
5
+ module ExcludeCommonMethods
6
+ ENUMERABLE_NAMES = Enumerable.instance_methods(false)
7
+
8
+ def self.apply!(profile)
9
+ ##
10
+ # Kernel Methods
11
+ ##
12
+
13
+ exclude_methods(profile, Kernel, [
14
+ :dup,
15
+ :initialize_dup,
16
+ :tap,
17
+ :send,
18
+ :public_send,
19
+ ])
20
+
21
+ ##
22
+ # Fundamental Types
23
+ ##
24
+
25
+ exclude_methods(profile, BasicObject, :"!=")
26
+ exclude_methods(profile, Method, :"[]")
27
+ exclude_methods(profile, Module, :new)
28
+ exclude_methods(profile, Class, :new)
29
+ exclude_methods(profile, Proc, :call, :yield)
30
+ exclude_methods(profile, Range, :each)
31
+ exclude_methods(profile, Integer, :times)
32
+
33
+ ##
34
+ # Value Types
35
+ ##
36
+
37
+ exclude_methods(profile, String, [
38
+ :sub,
39
+ :sub!,
40
+ :gsub,
41
+ :gsub!,
42
+ ])
43
+
44
+ ##
45
+ # Emumerables
46
+ ##
47
+
48
+ exclude_enumerable(profile, Enumerable)
49
+ exclude_enumerable(profile, Enumerator)
50
+
51
+ ##
52
+ # Collections
53
+ ##
54
+
55
+ exclude_enumerable(profile, Array, [
56
+ :each_index,
57
+ :map!,
58
+ :select!,
59
+ :reject!,
60
+ :collect!,
61
+ :sort!,
62
+ :sort_by!,
63
+ :index,
64
+ :delete_if,
65
+ :keep_if,
66
+ :drop_while,
67
+ :uniq,
68
+ :uniq!,
69
+ :"==",
70
+ :eql?,
71
+ :hash,
72
+ :to_json,
73
+ :as_json,
74
+ :encode_json,
75
+ ])
76
+
77
+ exclude_enumerable(profile, Hash, [
78
+ :dup,
79
+ :initialize_dup,
80
+ :fetch,
81
+ :"[]",
82
+ :"[]=",
83
+ :each_key,
84
+ :each_value,
85
+ :each_pair,
86
+ :map!,
87
+ :select!,
88
+ :reject!,
89
+ :collect!,
90
+ :delete_if,
91
+ :keep_if,
92
+ :slice,
93
+ :slice!,
94
+ :except,
95
+ :except!,
96
+ :"==",
97
+ :eql?,
98
+ :hash,
99
+ :to_json,
100
+ :as_json,
101
+ :encode_json,
102
+ ])
103
+
104
+ exclude_enumerable(profile, Set, [
105
+ :map!,
106
+ :select!,
107
+ :reject!,
108
+ :collect!,
109
+ :classify,
110
+ :delete_if,
111
+ :keep_if,
112
+ :divide,
113
+ :"==",
114
+ :eql?,
115
+ :hash,
116
+ :to_json,
117
+ :as_json,
118
+ :encode_json,
119
+ ])
120
+
121
+ ##
122
+ # Garbage Collection
123
+ ##
124
+
125
+ exclude_singleton_methods(profile, GC, [
126
+ :start
127
+ ])
128
+
129
+ ##
130
+ # Unicorn
131
+ ##
132
+
133
+ if defined?(Unicorn)
134
+ exclude_methods(profile, Unicorn::HttpServer, :process_client)
135
+ end
136
+
137
+ if defined?(Unicorn::OobGC)
138
+ exclude_methods(profile, Unicorn::OobGC, :process_client)
139
+ end
140
+
141
+ ##
142
+ # New Relic
143
+ ##
144
+
145
+ if defined?(NewRelic::Agent)
146
+ if defined?(NewRelic::Agent::Instrumentation::MiddlewareTracing)
147
+ exclude_methods(profile, NewRelic::Agent::Instrumentation::MiddlewareTracing, [
148
+ :call
149
+ ])
150
+ end
151
+
152
+ if defined?(NewRelic::Agent::MethodTracerHelpers)
153
+ exclude_methods(profile, NewRelic::Agent::MethodTracerHelpers, [
154
+ :trace_execution_scoped,
155
+ :log_errors,
156
+ ])
157
+
158
+ exclude_singleton_methods(profile, NewRelic::Agent::MethodTracerHelpers, [
159
+ :trace_execution_scoped,
160
+ :log_errors,
161
+ ])
162
+ end
163
+
164
+ if defined?(NewRelic::Agent::MethodTracer)
165
+ exclude_methods(profile, NewRelic::Agent::MethodTracer, [
166
+ :trace_execution_scoped,
167
+ :trace_execution_unscoped,
168
+ ])
169
+ end
170
+ end
171
+
172
+ ##
173
+ # Miscellaneous Methods
174
+ ##
175
+
176
+ if defined?(Mustache)
177
+ exclude_methods(profile, Mustache::Context, [
178
+ :fetch
179
+ ])
180
+ end
181
+ end
182
+
183
+ private
184
+
185
+ def self.exclude_enumerable(profile, mod, *method_or_methods)
186
+ exclude_methods(profile, mod, [:each, *method_or_methods])
187
+ exclude_methods(profile, mod, ENUMERABLE_NAMES)
188
+ end
189
+
190
+ def self.exclude_methods(profile, mod, *method_or_methods)
191
+ profile.exclude_methods!(mod, method_or_methods)
192
+ end
193
+
194
+ def self.exclude_singleton_methods(profile, mod, *method_or_methods)
195
+ profile.exclude_singleton_methods!(mod, method_or_methods)
196
+ end
197
+ end
198
+ end
@@ -0,0 +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,121 +1,78 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module RubyProf
4
+ # The MethodInfo class is used to track information about each method that is profiled.
5
+ # You cannot create a MethodInfo object directly, they are generated while running a profile.
4
6
  class MethodInfo
5
7
  include Comparable
6
8
 
7
- def <=>(other)
8
- if self.total_time < other.total_time
9
- -1
10
- elsif self.total_time > other.total_time
11
- 1
12
- elsif self.min_depth < other.min_depth
13
- 1
14
- elsif self.min_depth > other.min_depth
15
- -1
16
- else
17
- self.full_name <=> other.full_name
18
- end
9
+ # Returns the full name of a class. The interpretation of method names is:
10
+ #
11
+ # * MyObject#test - An method defined in a class
12
+ # * <Class:MyObject>#test - A method defined in a singleton class.
13
+ # * <Module:MyObject>#test - A method defined in a singleton module.
14
+ # * <Object:MyObject>#test - A method defined in a singleton object.
15
+ def full_name
16
+ decorated_class_name = case self.klass_flags
17
+ when 0x2
18
+ "<Class::#{klass_name}>"
19
+ when 0x4
20
+ "<Module::#{klass_name}>"
21
+ when 0x8
22
+ "<Object::#{klass_name}>"
23
+ else
24
+ klass_name
25
+ end
26
+
27
+ "#{decorated_class_name}##{method_name}"
19
28
  end
20
29
 
30
+ # The number of times this method was called
21
31
  def called
22
- @called ||= begin
23
- call_infos.inject(0) do |sum, call_info|
24
- sum + call_info.called
25
- end
26
- end
32
+ self.measurement.called
27
33
  end
28
34
 
35
+ # The total time this method took - includes self time + wait time + child time
29
36
  def total_time
30
- @total_time ||= begin
31
- call_infos.inject(0) do |sum, call_info|
32
- sum += call_info.total_time if !call_info.recursive?
33
- sum
34
- end
35
- end
37
+ self.measurement.total_time
36
38
  end
37
39
 
40
+ # The time this method took to execute
38
41
  def self_time
39
- @self_time ||= begin
40
- call_infos.inject(0) do |sum, call_info|
41
- sum += call_info.self_time if !call_info.recursive?
42
- sum
43
- end
44
- end
42
+ self.measurement.self_time
45
43
  end
46
44
 
45
+ # The time this method waited for other fibers/threads to execute
47
46
  def wait_time
48
- @wait_time ||= begin
49
- call_infos.inject(0) do |sum, call_info|
50
- sum += call_info.wait_time if !call_info.recursive?
51
- sum
52
- end
53
- end
47
+ self.measurement.wait_time
54
48
  end
55
49
 
50
+ # The time this method's children took to execute
56
51
  def children_time
57
- @children_time ||= begin
58
- call_infos.inject(0) do |sum, call_info|
59
- sum += call_info.children_time if !call_info.recursive?
60
- sum
61
- end
62
- end
63
- end
64
-
65
- def min_depth
66
- @min_depth ||= call_infos.map(&:depth).min
67
- end
68
-
69
- def root?
70
- @root ||= begin
71
- call_infos.find do |call_info|
72
- not call_info.root?
73
- end.nil?
74
- end
75
- end
76
-
77
- def children
78
- @children ||= call_infos.map(&:children).flatten
52
+ self.total_time - self.self_time - self.wait_time
79
53
  end
80
54
 
81
- def parents
82
- @parents ||= call_infos.map(&:parent)
83
- end
84
-
85
- def aggregate_parents
86
- # group call infos based on their parents
87
- groups = self.call_infos.each_with_object({}) do |call_info, hash|
88
- key = call_info.parent ? call_info.parent.target : self
89
- (hash[key] ||= []) << call_info
90
- end
91
-
92
- groups.map do |key, value|
93
- AggregateCallInfo.new(value, self)
94
- end
95
- end
96
-
97
- def aggregate_children
98
- # group call infos based on their targets
99
- groups = self.children.each_with_object({}) do |call_info, hash|
100
- key = call_info.target
101
- (hash[key] ||= []) << call_info
102
- end
103
-
104
- groups.map do |key, value|
105
- AggregateCallInfo.new(value, self)
55
+ # :enddoc:
56
+ def <=>(other)
57
+ if other.nil?
58
+ -1
59
+ elsif self.full_name == other.full_name
60
+ 0
61
+ elsif self.total_time < other.total_time
62
+ -1
63
+ elsif self.total_time > other.total_time
64
+ 1
65
+ elsif self.call_trees.min_depth < other.call_trees.min_depth
66
+ 1
67
+ elsif self.call_trees.min_depth > other.call_trees.min_depth
68
+ -1
69
+ else
70
+ self.full_name <=> other.full_name
106
71
  end
107
72
  end
108
73
 
109
74
  def to_s
110
75
  "#{self.full_name} (c: #{self.called}, tt: #{self.total_time}, st: #{self.self_time}, wt: #{wait_time}, ct: #{self.children_time})"
111
76
  end
112
-
113
- # remove method from the call graph. should not be called directly.
114
- def eliminate!
115
- # $stderr.puts "eliminating #{self}"
116
- call_infos.each{ |call_info| call_info.eliminate! }
117
- call_infos.clear
118
- end
119
-
120
77
  end
121
78
  end