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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +23 -0
  3. data/LICENSE +2 -2
  4. data/README.rdoc +1 -483
  5. data/Rakefile +3 -6
  6. data/bin/ruby-prof +65 -30
  7. data/ext/ruby_prof/extconf.rb +6 -38
  8. data/ext/ruby_prof/rp_allocation.c +292 -0
  9. data/ext/ruby_prof/rp_allocation.h +31 -0
  10. data/ext/ruby_prof/rp_call_info.c +137 -279
  11. data/ext/ruby_prof/rp_call_info.h +16 -34
  12. data/ext/ruby_prof/rp_measure_allocations.c +25 -49
  13. data/ext/ruby_prof/rp_measure_memory.c +21 -56
  14. data/ext/ruby_prof/rp_measure_process_time.c +28 -36
  15. data/ext/ruby_prof/rp_measure_wall_time.c +36 -19
  16. data/ext/ruby_prof/rp_measurement.c +236 -0
  17. data/ext/ruby_prof/rp_measurement.h +49 -0
  18. data/ext/ruby_prof/rp_method.c +395 -383
  19. data/ext/ruby_prof/rp_method.h +34 -39
  20. data/ext/ruby_prof/rp_profile.c +881 -0
  21. data/ext/ruby_prof/rp_profile.h +36 -0
  22. data/ext/ruby_prof/rp_stack.c +103 -80
  23. data/ext/ruby_prof/rp_stack.h +5 -12
  24. data/ext/ruby_prof/rp_thread.c +149 -88
  25. data/ext/ruby_prof/rp_thread.h +15 -6
  26. data/ext/ruby_prof/ruby_prof.c +11 -757
  27. data/ext/ruby_prof/ruby_prof.h +4 -47
  28. data/ext/ruby_prof/vc/ruby_prof.vcxproj +10 -8
  29. data/lib/ruby-prof.rb +2 -17
  30. data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
  31. data/lib/ruby-prof/call_info.rb +35 -93
  32. data/lib/ruby-prof/call_info_visitor.rb +19 -21
  33. data/lib/ruby-prof/compatibility.rb +37 -107
  34. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  35. data/lib/ruby-prof/measurement.rb +14 -0
  36. data/lib/ruby-prof/method_info.rb +52 -83
  37. data/lib/ruby-prof/printers/abstract_printer.rb +66 -52
  38. data/lib/ruby-prof/printers/call_info_printer.rb +13 -3
  39. data/lib/ruby-prof/printers/call_stack_printer.rb +32 -28
  40. data/lib/ruby-prof/printers/call_tree_printer.rb +20 -12
  41. data/lib/ruby-prof/printers/dot_printer.rb +5 -5
  42. data/lib/ruby-prof/printers/flat_printer.rb +6 -24
  43. data/lib/ruby-prof/printers/graph_html_printer.rb +7 -192
  44. data/lib/ruby-prof/printers/graph_printer.rb +13 -15
  45. data/lib/ruby-prof/printers/multi_printer.rb +66 -23
  46. data/lib/ruby-prof/profile.rb +10 -3
  47. data/lib/ruby-prof/rack.rb +0 -3
  48. data/lib/ruby-prof/thread.rb +12 -12
  49. data/lib/ruby-prof/version.rb +1 -1
  50. data/ruby-prof.gemspec +2 -2
  51. data/test/abstract_printer_test.rb +0 -27
  52. data/test/alias_test.rb +129 -0
  53. data/test/basic_test.rb +41 -40
  54. data/test/call_info_visitor_test.rb +3 -3
  55. data/test/dynamic_method_test.rb +0 -2
  56. data/test/line_number_test.rb +120 -39
  57. data/test/marshal_test.rb +119 -0
  58. data/test/measure_allocations.rb +30 -0
  59. data/test/measure_allocations_test.rb +371 -12
  60. data/test/measure_allocations_trace_test.rb +385 -0
  61. data/test/measure_memory_trace_test.rb +756 -0
  62. data/test/measure_process_time_test.rb +821 -33
  63. data/test/measure_times.rb +54 -0
  64. data/test/measure_wall_time_test.rb +349 -145
  65. data/test/multi_printer_test.rb +1 -34
  66. data/test/parser_timings.rb +24 -0
  67. data/test/pause_resume_test.rb +5 -5
  68. data/test/prime.rb +2 -0
  69. data/test/printer_call_tree_test.rb +31 -0
  70. data/test/printer_flat_test.rb +68 -0
  71. data/test/printer_graph_html_test.rb +60 -0
  72. data/test/printer_graph_test.rb +41 -0
  73. data/test/printers_test.rb +32 -166
  74. data/test/printing_recursive_graph_test.rb +26 -72
  75. data/test/recursive_test.rb +72 -77
  76. data/test/stack_printer_test.rb +2 -15
  77. data/test/start_stop_test.rb +22 -25
  78. data/test/test_helper.rb +5 -248
  79. data/test/thread_test.rb +11 -54
  80. data/test/unique_call_path_test.rb +16 -28
  81. data/test/yarv_test.rb +1 -0
  82. metadata +24 -34
  83. data/examples/flat.txt +0 -50
  84. data/examples/graph.dot +0 -84
  85. data/examples/graph.html +0 -823
  86. data/examples/graph.txt +0 -139
  87. data/examples/multi.flat.txt +0 -23
  88. data/examples/multi.graph.html +0 -760
  89. data/examples/multi.grind.dat +0 -114
  90. data/examples/multi.stack.html +0 -547
  91. data/examples/stack.html +0 -547
  92. data/ext/ruby_prof/rp_measure.c +0 -40
  93. data/ext/ruby_prof/rp_measure.h +0 -45
  94. data/ext/ruby_prof/rp_measure_cpu_time.c +0 -136
  95. data/ext/ruby_prof/rp_measure_gc_runs.c +0 -73
  96. data/ext/ruby_prof/rp_measure_gc_time.c +0 -60
  97. data/lib/ruby-prof/aggregate_call_info.rb +0 -76
  98. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +0 -83
  99. data/lib/ruby-prof/profile/exclude_common_methods.rb +0 -207
  100. data/lib/ruby-prof/profile/legacy_method_elimination.rb +0 -50
  101. data/test/aggregate_test.rb +0 -136
  102. data/test/block_test.rb +0 -74
  103. data/test/call_info_test.rb +0 -78
  104. data/test/fiber_test.rb +0 -79
  105. data/test/issue137_test.rb +0 -63
  106. data/test/measure_cpu_time_test.rb +0 -212
  107. data/test/measure_gc_runs_test.rb +0 -32
  108. data/test/measure_gc_time_test.rb +0 -36
  109. data/test/measure_memory_test.rb +0 -33
  110. data/test/method_elimination_test.rb +0 -84
  111. data/test/module_test.rb +0 -45
  112. data/test/stack_test.rb +0 -138
@@ -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
- # part of this class is defined in C code.
6
- # it provides the following attributes pertaining to tree structure:
7
- # depth: tree level (0 == root)
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
- def stack
19
- @stack ||= begin
20
- methods = Array.new
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
- def call_sequence
32
- @call_sequence ||= begin
33
- stack.map {|method| method.full_name}.join('->')
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
- def descendent_of(other)
42
- p = self.parent
43
- while p && p != other && p.depth > other.depth
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
- def self.roots_of(call_infos)
50
- roots = []
51
- sorted = call_infos.sort_by(&:depth).reverse
52
- while call_info = sorted.shift
53
- roots << call_info unless sorted.any?{|p| call_info.descendent_of(p)}
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
- "#{target.full_name} (c: #{called}, tt: #{total_time}, st: #{self_time}, ct: #{children_time})"
50
+ "#{parent ? parent.full_name : '<nil>'} - #{target.full_name}"
60
51
  end
61
52
 
62
53
  def inspect
63
- super + "(#{target.full_name}, d: #{depth}, c: #{called}, tt: #{total_time}, st: #{self_time}, ct: #{children_time})"
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
- def initialize(call_infos)
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.children.each do |child|
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 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