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.
- checksums.yaml +4 -4
- data/CHANGES +44 -1
- data/LICENSE +2 -2
- data/README.rdoc +1 -483
- data/Rakefile +3 -6
- data/bin/ruby-prof +111 -128
- data/ext/ruby_prof/extconf.rb +6 -38
- data/ext/ruby_prof/rp_aggregate_call_tree.c +41 -0
- data/ext/ruby_prof/rp_aggregate_call_tree.h +13 -0
- data/ext/ruby_prof/rp_allocation.c +259 -0
- data/ext/ruby_prof/rp_allocation.h +31 -0
- data/ext/ruby_prof/rp_call_tree.c +353 -0
- data/ext/ruby_prof/rp_call_tree.h +43 -0
- data/ext/ruby_prof/rp_call_trees.c +266 -0
- data/ext/ruby_prof/rp_call_trees.h +29 -0
- data/ext/ruby_prof/rp_measure_allocations.c +25 -51
- data/ext/ruby_prof/rp_measure_memory.c +21 -56
- data/ext/ruby_prof/rp_measure_process_time.c +37 -43
- data/ext/ruby_prof/rp_measure_wall_time.c +40 -21
- data/ext/ruby_prof/rp_measurement.c +221 -0
- data/ext/ruby_prof/rp_measurement.h +50 -0
- data/ext/ruby_prof/rp_method.c +279 -439
- data/ext/ruby_prof/rp_method.h +33 -45
- data/ext/ruby_prof/rp_profile.c +902 -0
- data/ext/ruby_prof/rp_profile.h +36 -0
- data/ext/ruby_prof/rp_stack.c +163 -132
- data/ext/ruby_prof/rp_stack.h +18 -28
- data/ext/ruby_prof/rp_thread.c +192 -124
- data/ext/ruby_prof/rp_thread.h +18 -8
- data/ext/ruby_prof/ruby_prof.c +36 -778
- data/ext/ruby_prof/ruby_prof.h +11 -45
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +18 -12
- data/lib/ruby-prof.rb +4 -21
- data/lib/ruby-prof/assets/call_stack_printer.html.erb +710 -0
- data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
- data/lib/ruby-prof/assets/graph_printer.html.erb +355 -0
- data/lib/ruby-prof/call_tree.rb +57 -0
- data/lib/ruby-prof/call_tree_visitor.rb +36 -0
- data/lib/ruby-prof/compatibility.rb +37 -107
- data/lib/ruby-prof/exclude_common_methods.rb +198 -0
- data/lib/ruby-prof/measurement.rb +17 -0
- data/lib/ruby-prof/method_info.rb +47 -90
- data/lib/ruby-prof/printers/abstract_printer.rb +73 -50
- data/lib/ruby-prof/printers/call_info_printer.rb +24 -12
- data/lib/ruby-prof/printers/call_stack_printer.rb +66 -152
- data/lib/ruby-prof/printers/call_tree_printer.rb +20 -12
- data/lib/ruby-prof/printers/dot_printer.rb +5 -5
- data/lib/ruby-prof/printers/flat_printer.rb +6 -24
- data/lib/ruby-prof/printers/graph_html_printer.rb +6 -192
- data/lib/ruby-prof/printers/graph_printer.rb +11 -14
- data/lib/ruby-prof/printers/multi_printer.rb +66 -23
- data/lib/ruby-prof/profile.rb +10 -3
- data/lib/ruby-prof/thread.rb +5 -20
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +9 -2
- data/test/abstract_printer_test.rb +0 -27
- data/test/alias_test.rb +126 -0
- data/test/basic_test.rb +1 -86
- data/test/call_tree_visitor_test.rb +32 -0
- data/test/call_trees_test.rb +66 -0
- data/test/dynamic_method_test.rb +0 -2
- data/test/exclude_methods_test.rb +17 -12
- data/test/fiber_test.rb +214 -23
- data/test/gc_test.rb +105 -0
- data/test/inverse_call_tree_test.rb +175 -0
- data/test/line_number_test.rb +118 -40
- data/test/marshal_test.rb +115 -0
- data/test/measure_allocations.rb +30 -0
- data/test/measure_allocations_test.rb +361 -12
- data/test/measure_allocations_trace_test.rb +375 -0
- data/test/measure_memory_trace_test.rb +1101 -0
- data/test/measure_process_time_test.rb +757 -33
- data/test/measure_times.rb +56 -0
- data/test/measure_wall_time_test.rb +329 -149
- data/test/multi_printer_test.rb +1 -34
- data/test/pause_resume_test.rb +24 -15
- data/test/prime.rb +1 -1
- data/test/prime_script.rb +6 -0
- data/test/printer_call_stack_test.rb +28 -0
- data/test/printer_call_tree_test.rb +31 -0
- data/test/printer_flat_test.rb +68 -0
- data/test/printer_graph_html_test.rb +60 -0
- data/test/printer_graph_test.rb +41 -0
- data/test/printers_test.rb +32 -166
- data/test/printing_recursive_graph_test.rb +26 -72
- data/test/recursive_test.rb +68 -77
- data/test/stack_printer_test.rb +2 -15
- data/test/start_stop_test.rb +22 -25
- data/test/test_helper.rb +6 -261
- data/test/thread_test.rb +11 -54
- data/test/unique_call_path_test.rb +25 -107
- data/test/yarv_test.rb +1 -0
- metadata +43 -41
- data/examples/flat.txt +0 -50
- data/examples/graph.dot +0 -84
- data/examples/graph.html +0 -823
- data/examples/graph.txt +0 -139
- data/examples/multi.flat.txt +0 -23
- data/examples/multi.graph.html +0 -760
- data/examples/multi.grind.dat +0 -114
- data/examples/multi.stack.html +0 -547
- data/examples/stack.html +0 -547
- data/ext/ruby_prof/rp_call_info.c +0 -425
- data/ext/ruby_prof/rp_call_info.h +0 -53
- data/ext/ruby_prof/rp_measure.c +0 -40
- data/ext/ruby_prof/rp_measure.h +0 -45
- data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
- data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
- data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
- data/lib/ruby-prof/aggregate_call_info.rb +0 -76
- data/lib/ruby-prof/assets/call_stack_printer.css.html +0 -117
- data/lib/ruby-prof/assets/call_stack_printer.js.html +0 -385
- data/lib/ruby-prof/call_info.rb +0 -115
- data/lib/ruby-prof/call_info_visitor.rb +0 -40
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -83
- data/lib/ruby-prof/profile/exclude_common_methods.rb +0 -207
- data/lib/ruby-prof/profile/legacy_method_elimination.rb +0 -50
- data/test/aggregate_test.rb +0 -136
- data/test/block_test.rb +0 -74
- data/test/call_info_test.rb +0 -78
- data/test/call_info_visitor_test.rb +0 -31
- data/test/issue137_test.rb +0 -63
- data/test/measure_cpu_time_test.rb +0 -212
- data/test/measure_gc_runs_test.rb +0 -32
- data/test/measure_gc_time_test.rb +0 -36
- data/test/measure_memory_test.rb +0 -33
- data/test/method_elimination_test.rb +0 -84
- data/test/module_test.rb +0 -45
- data/test/stack_test.rb +0 -138
@@ -1,53 +1,16 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
# These methods are
|
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
|
44
|
-
# *RubyProf::PROCESS_TIME
|
45
|
-
# *RubyProf::
|
46
|
-
# *RubyProf::
|
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 -
|
61
|
-
# *RubyProf::PROCESS_TIME -
|
62
|
-
# *RubyProf::
|
63
|
-
# *RubyProf::
|
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
|
-
|
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
|
-
#
|
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
|
-
#
|
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
|
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
|
-
#
|
77
|
+
# Profiles a block
|
143
78
|
def self.profile(options = {}, &block)
|
144
79
|
ensure_not_running!
|
145
|
-
|
146
|
-
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
|
-
|
155
|
-
|
156
|
-
|
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
|
-
|
160
|
-
|
94
|
+
# :nodoc:
|
95
|
+
def self.start_script(script)
|
96
|
+
start
|
97
|
+
load script
|
161
98
|
end
|
162
99
|
|
163
|
-
|
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.
|
171
|
-
|
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.
|
176
|
-
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
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
|