ruby-prof 0.18.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES +23 -0
- data/LICENSE +2 -2
- data/README.rdoc +1 -483
- data/Rakefile +3 -6
- data/bin/ruby-prof +65 -30
- data/ext/ruby_prof/extconf.rb +6 -38
- data/ext/ruby_prof/rp_allocation.c +292 -0
- data/ext/ruby_prof/rp_allocation.h +31 -0
- data/ext/ruby_prof/rp_call_info.c +137 -279
- data/ext/ruby_prof/rp_call_info.h +16 -34
- data/ext/ruby_prof/rp_measure_allocations.c +25 -49
- data/ext/ruby_prof/rp_measure_memory.c +21 -56
- data/ext/ruby_prof/rp_measure_process_time.c +28 -36
- data/ext/ruby_prof/rp_measure_wall_time.c +36 -19
- data/ext/ruby_prof/rp_measurement.c +236 -0
- data/ext/ruby_prof/rp_measurement.h +49 -0
- data/ext/ruby_prof/rp_method.c +395 -383
- data/ext/ruby_prof/rp_method.h +34 -39
- data/ext/ruby_prof/rp_profile.c +881 -0
- data/ext/ruby_prof/rp_profile.h +36 -0
- data/ext/ruby_prof/rp_stack.c +103 -80
- data/ext/ruby_prof/rp_stack.h +5 -12
- data/ext/ruby_prof/rp_thread.c +149 -88
- data/ext/ruby_prof/rp_thread.h +15 -6
- data/ext/ruby_prof/ruby_prof.c +11 -757
- data/ext/ruby_prof/ruby_prof.h +4 -47
- data/ext/ruby_prof/vc/ruby_prof.vcxproj +10 -8
- data/lib/ruby-prof.rb +2 -17
- data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
- data/lib/ruby-prof/call_info.rb +35 -93
- data/lib/ruby-prof/call_info_visitor.rb +19 -21
- data/lib/ruby-prof/compatibility.rb +37 -107
- data/lib/ruby-prof/exclude_common_methods.rb +198 -0
- data/lib/ruby-prof/measurement.rb +14 -0
- data/lib/ruby-prof/method_info.rb +52 -83
- data/lib/ruby-prof/printers/abstract_printer.rb +66 -52
- data/lib/ruby-prof/printers/call_info_printer.rb +13 -3
- data/lib/ruby-prof/printers/call_stack_printer.rb +32 -28
- 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 +7 -192
- data/lib/ruby-prof/printers/graph_printer.rb +13 -15
- data/lib/ruby-prof/printers/multi_printer.rb +66 -23
- data/lib/ruby-prof/profile.rb +10 -3
- data/lib/ruby-prof/rack.rb +0 -3
- data/lib/ruby-prof/thread.rb +12 -12
- data/lib/ruby-prof/version.rb +1 -1
- data/ruby-prof.gemspec +2 -2
- data/test/abstract_printer_test.rb +0 -27
- data/test/alias_test.rb +129 -0
- data/test/basic_test.rb +41 -40
- data/test/call_info_visitor_test.rb +3 -3
- data/test/dynamic_method_test.rb +0 -2
- data/test/line_number_test.rb +120 -39
- data/test/marshal_test.rb +119 -0
- data/test/measure_allocations.rb +30 -0
- data/test/measure_allocations_test.rb +371 -12
- data/test/measure_allocations_trace_test.rb +385 -0
- data/test/measure_memory_trace_test.rb +756 -0
- data/test/measure_process_time_test.rb +821 -33
- data/test/measure_times.rb +54 -0
- data/test/measure_wall_time_test.rb +349 -145
- data/test/multi_printer_test.rb +1 -34
- data/test/parser_timings.rb +24 -0
- data/test/pause_resume_test.rb +5 -5
- data/test/prime.rb +2 -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 +72 -77
- data/test/stack_printer_test.rb +2 -15
- data/test/start_stop_test.rb +22 -25
- data/test/test_helper.rb +5 -248
- data/test/thread_test.rb +11 -54
- data/test/unique_call_path_test.rb +16 -28
- data/test/yarv_test.rb +1 -0
- metadata +24 -34
- 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_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/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/fiber_test.rb +0 -79
- 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
data/lib/ruby-prof/call_info.rb
CHANGED
@@ -1,115 +1,57 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
module RubyProf
|
4
|
+
# The CallInfo 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 CallInfo has a parent and target method. You cannot create a CallInfo object directly,
|
7
|
+
# they are generated while running a profile.
|
4
8
|
class CallInfo
|
5
|
-
#
|
6
|
-
|
7
|
-
|
8
|
-
# parent: parent call info (can be nil)
|
9
|
-
# children: array of call info children (can be empty)
|
10
|
-
# target: method info (containing an array of call infos)
|
11
|
-
|
12
|
-
def children_time
|
13
|
-
children.inject(0) do |sum, call_info|
|
14
|
-
sum += call_info.total_time
|
15
|
-
end
|
9
|
+
# The number of times the parent method called the target method
|
10
|
+
def called
|
11
|
+
self.measurement.called
|
16
12
|
end
|
17
13
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
call_info = self
|
22
|
-
|
23
|
-
while call_info
|
24
|
-
methods << call_info.target
|
25
|
-
call_info = call_info.parent
|
26
|
-
end
|
27
|
-
methods.reverse
|
28
|
-
end
|
14
|
+
# The total time resulting from the parent method calling the target method
|
15
|
+
def total_time
|
16
|
+
self.measurement.total_time
|
29
17
|
end
|
30
18
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def root?
|
38
|
-
self.parent.nil?
|
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
|
39
22
|
end
|
40
23
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
p = p.parent
|
45
|
-
end
|
46
|
-
p == other
|
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
|
47
27
|
end
|
48
28
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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 CallInfo instances. The comparison is based on the CallInfo#parent, CallInfo#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
|
54
45
|
end
|
55
|
-
roots
|
56
46
|
end
|
57
47
|
|
48
|
+
# :nodoc:
|
58
49
|
def to_s
|
59
|
-
"#{
|
50
|
+
"#{parent ? parent.full_name : '<nil>'} - #{target.full_name}"
|
60
51
|
end
|
61
52
|
|
62
53
|
def inspect
|
63
|
-
super + "(#{
|
64
|
-
end
|
65
|
-
|
66
|
-
# eliminate call info from the call tree.
|
67
|
-
# adds self and wait time to parent and attaches called methods to parent.
|
68
|
-
# merges call trees for methods called from both praent end self.
|
69
|
-
def eliminate!
|
70
|
-
# puts "eliminating #{self}"
|
71
|
-
return unless parent
|
72
|
-
parent.add_self_time(self)
|
73
|
-
parent.add_wait_time(self)
|
74
|
-
children.each do |kid|
|
75
|
-
if call = parent.find_call(kid)
|
76
|
-
call.merge_call_tree(kid)
|
77
|
-
else
|
78
|
-
parent.children << kid
|
79
|
-
# $stderr.puts "setting parent of #{kid}\nto #{parent}"
|
80
|
-
kid.parent = parent
|
81
|
-
end
|
82
|
-
end
|
83
|
-
parent.children.delete(self)
|
84
|
-
end
|
85
|
-
|
86
|
-
# find a specific call in list of children. returns nil if not found.
|
87
|
-
# note: there can't be more than one child with a given target method. in other words:
|
88
|
-
# x.children.grep{|y|y.target==m}.size <= 1 for all method infos m and call infos x
|
89
|
-
def find_call(other)
|
90
|
-
matching = children.select { |kid| kid.target == other.target }
|
91
|
-
raise "inconsistent call tree" unless matching.size <= 1
|
92
|
-
matching.first
|
93
|
-
end
|
94
|
-
|
95
|
-
# merge two call trees. adds self, wait, and total time of other to self and merges children of other into children of self.
|
96
|
-
def merge_call_tree(other)
|
97
|
-
# $stderr.puts "merging #{self}\nand #{other}"
|
98
|
-
self.called += other.called
|
99
|
-
add_self_time(other)
|
100
|
-
add_wait_time(other)
|
101
|
-
add_total_time(other)
|
102
|
-
other.children.each do |other_kid|
|
103
|
-
if kid = find_call(other_kid)
|
104
|
-
# $stderr.puts "merging kids"
|
105
|
-
kid.merge_call_tree(other_kid)
|
106
|
-
else
|
107
|
-
other_kid.parent = self
|
108
|
-
children << other_kid
|
109
|
-
end
|
110
|
-
end
|
111
|
-
other.children.clear
|
112
|
-
other.target.call_infos.delete(other)
|
54
|
+
super + "(#{self.to_s})"
|
113
55
|
end
|
114
56
|
end
|
115
57
|
end
|
@@ -1,24 +1,22 @@
|
|
1
|
-
# The call info visitor class does a depth-first traversal across a
|
2
|
-
# list of method infos. At each call_info node, the visitor executes
|
3
|
-
# the block provided in the #visit method. The block is passed two
|
4
|
-
# parameters, the event and the call_info instance. Event will be
|
5
|
-
# either :enter or :exit.
|
6
|
-
#
|
7
|
-
# visitor = RubyProf::CallInfoVisitor.new(result.threads.first.top_call_infos)
|
8
|
-
#
|
9
|
-
# method_names = Array.new
|
10
|
-
#
|
11
|
-
# visitor.visit do |call_info, event|
|
12
|
-
# method_names << call_info.target.full_name if event == :enter
|
13
|
-
# end
|
14
|
-
#
|
15
|
-
# puts method_names
|
16
|
-
|
17
1
|
module RubyProf
|
2
|
+
# The call info visitor class does a depth-first traversal across a
|
3
|
+
# list of method infos. At each call_info node, the visitor executes
|
4
|
+
# the block provided in the #visit method. The block is passed two
|
5
|
+
# parameters, the event and the call_info instance. Event will be
|
6
|
+
# either :enter or :exit.
|
7
|
+
#
|
8
|
+
# visitor = RubyProf::CallInfoVisitor.new(result.threads.first.root_methods)
|
9
|
+
#
|
10
|
+
# method_names = Array.new
|
11
|
+
#
|
12
|
+
# visitor.visit do |call_info, event|
|
13
|
+
# method_names << call_info.target.full_name if event == :enter
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# puts method_names
|
18
17
|
class CallInfoVisitor
|
19
|
-
|
20
|
-
|
21
|
-
@call_infos = CallInfo.roots_of(call_infos)
|
18
|
+
def initialize(root_methods)
|
19
|
+
@call_infos = root_methods.map(&:callers).flatten
|
22
20
|
end
|
23
21
|
|
24
22
|
def visit(&block)
|
@@ -28,13 +26,13 @@ module RubyProf
|
|
28
26
|
end
|
29
27
|
|
30
28
|
private
|
29
|
+
|
31
30
|
def visit_call_info(call_info, &block)
|
32
31
|
yield call_info, :enter
|
33
|
-
call_info.
|
32
|
+
call_info.target.callees.each do |child|
|
34
33
|
visit_call_info(child, &block)
|
35
34
|
end
|
36
35
|
yield call_info, :exit
|
37
36
|
end
|
38
37
|
end
|
39
|
-
|
40
38
|
end
|
@@ -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
|