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
data/Rakefile CHANGED
@@ -40,7 +40,7 @@ Rake::ExtensionTask.new do |ext|
40
40
  ext.ext_dir = "ext/#{SO_NAME}"
41
41
  ext.lib_dir = "lib/#{RUBY_VERSION}"
42
42
  ext.cross_compile = true
43
- ext.cross_platform = ['x86-mswin32-60', 'x86-mingw32-60']
43
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
44
44
  end
45
45
 
46
46
  # Rake task to build the default package
@@ -80,12 +80,9 @@ RDoc::Task.new("rdoc") do |rdoc|
80
80
  rdoc.options << '--main' << 'README.rdoc'
81
81
  rdoc.rdoc_files.include('bin/*',
82
82
  'doc/*.rdoc',
83
- 'examples/flat.txt',
84
- 'examples/graph.txt',
85
- 'examples/graph.html',
86
83
  'lib/**/*.rb',
87
- 'ext/ruby_prof/ruby_prof.c',
88
- 'ext/ruby_prof/measure_*.h',
84
+ 'ext/ruby_prof/*.c',
85
+ 'ext/ruby_prof/*.h',
89
86
  'README.rdoc',
90
87
  'LICENSE')
91
88
  end
@@ -1,20 +1,6 @@
1
1
  #! /usr/bin/env ruby
2
2
 
3
- # == Synopsis
4
- #
5
- # Profiles a Ruby program.
6
- #
7
- # == Usage
8
- #
9
- # ruby_prof [options] <script.rb> [--] [script-options]"
10
- #
11
- # Various options:
12
- # run "$ ruby-prof --help" to see them
13
- #
14
- # See also the readme "reports" section for the various outputs
15
-
16
3
  # First require ruby-prof
17
- require 'rubygems'
18
4
  require 'ruby-prof'
19
5
 
20
6
  # Now setup option parser
@@ -22,8 +8,50 @@ require 'ostruct'
22
8
  require 'optparse'
23
9
 
24
10
  module RubyProf
11
+ # == Synopsis
12
+ #
13
+ # Profiles a Ruby program.
14
+ #
15
+ # == Usage
16
+ # ruby-prof [options] <script.rb> [--] [profiled-script-command-line-options]
17
+ #
18
+ # Options:
19
+ # -p, --printer=printer Select a printer:
20
+ # flat - Prints a flat profile as text (default).
21
+ # graph - Prints a graph profile as text.
22
+ # graph_html - Prints a graph profile as html.
23
+ # call_tree - format for KCacheGrind
24
+ # call_stack - prints a HTML visualization of the call tree
25
+ # dot - Prints a graph profile as a dot file
26
+ # multi - Creates several reports in output directory
27
+ # -m, --min_percent=min_percent The minimum percent a method must take before
28
+ # being included in output reports.
29
+ # This option is not supported for call tree.
30
+ # -f, --file=path Output results to a file instead of standard out.
31
+ # --mode=measure_mode Select what ruby-prof should measure:
32
+ # wall - Wall time (default).
33
+ # process - Process time.
34
+ # allocations - Object allocations (requires patched Ruby interpreter).
35
+ # memory - Allocated memory in KB (requires patched Ruby interpreter).
36
+ # -s, --sort=sort_mode Select how ruby-prof results should be sorted:
37
+ # total - Total time
38
+ # self - Self time
39
+ # wait - Wait time
40
+ # child - Child time
41
+ # --allow_exceptions Raise exceptions encountered during profiling (true) or suppress them (false)
42
+ # -R, --require-noprof=lib require a specific library (not profiled)
43
+ # -E, --eval-noprof=code execute the ruby statements (not profiled)
44
+ # --exclude=methods A comma separated list of methods to exclude.
45
+ # Specify instance methods via # (Integer#times)
46
+ # Specify class methods via . (Integer.superclass)
47
+ # --exclude-common Remove common methods from the profile
48
+ # -h, --help Show help message
49
+ # -v, --version version Show version (1.1.0)
50
+
25
51
  class Cmd
52
+ # :enddoc:
26
53
  attr_accessor :options
54
+ attr_reader :profile
27
55
 
28
56
  def initialize
29
57
  setup_options
@@ -36,15 +64,52 @@ module RubyProf
36
64
  def setup_options
37
65
  @options = OpenStruct.new
38
66
  options.printer = RubyProf::FlatPrinter
67
+ options.measure_mode = RubyProf::WALL_TIME
39
68
  options.min_percent = 0
40
69
  options.file = nil
41
- options.replace_prog_name = false
42
- options.specialized_instruction = false
43
-
70
+ options.allow_exceptions = false
71
+ options.exclude_common = false
72
+ options.exclude = Array.new
44
73
  options.pre_libs = Array.new
45
74
  options.pre_execs = Array.new
46
75
  end
47
76
 
77
+ # This is copied from ActiveSupport:
78
+ def constantize(camel_cased_word)
79
+ if !camel_cased_word.include?("::")
80
+ Object.const_get(camel_cased_word)
81
+ else
82
+ names = camel_cased_word.split("::")
83
+
84
+ # Trigger a built-in NameError exception including the ill-formed constant in the message.
85
+ Object.const_get(camel_cased_word) if names.empty?
86
+
87
+ # Remove the first blank element in case of '::ClassName' notation.
88
+ names.shift if names.size > 1 && names.first.empty?
89
+
90
+ names.inject(Object) do |constant, name|
91
+ if constant == Object
92
+ constant.const_get(name)
93
+ else
94
+ candidate = constant.const_get(name)
95
+ next candidate if constant.const_defined?(name, false)
96
+ next candidate unless Object.const_defined?(name)
97
+
98
+ # Go down the ancestors to check if it is owned directly. The check
99
+ # stops when we reach Object or the end of ancestors tree.
100
+ constant = constant.ancestors.inject(constant) do |const, ancestor|
101
+ break const if ancestor == Object
102
+ break ancestor if ancestor.const_defined?(name, false)
103
+ const
104
+ end
105
+
106
+ # owner is in Object, so raise
107
+ constant.const_get(name, false)
108
+ end
109
+ end
110
+ end
111
+ end
112
+
48
113
  def option_parser
49
114
  OptionParser.new do |opts|
50
115
  opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
@@ -56,7 +121,6 @@ module RubyProf
56
121
  opts.on('-p printer', '--printer=printer', [:flat, :flat_with_line_numbers, :graph, :graph_html, :call_tree, :call_stack, :dot, :multi],
57
122
  'Select a printer:',
58
123
  ' flat - Prints a flat profile as text (default).',
59
- ' flat_with_line_numbers - same as flat, with line numbers.',
60
124
  ' graph - Prints a graph profile as text.',
61
125
  ' graph_html - Prints a graph profile as html.',
62
126
  ' call_tree - format for KCacheGrind',
@@ -65,12 +129,9 @@ module RubyProf
65
129
  ' multi - Creates several reports in output directory'
66
130
  ) do |printer|
67
131
 
68
-
69
132
  case printer
70
133
  when :flat
71
134
  options.printer = RubyProf::FlatPrinter
72
- when :flat_with_line_numbers
73
- options.printer = RubyProf::FlatPrinterWithLineNumbers
74
135
  when :graph
75
136
  options.printer = RubyProf::GraphPrinter
76
137
  when :graph_html
@@ -89,7 +150,7 @@ module RubyProf
89
150
  opts.on('-m min_percent', '--min_percent=min_percent', Float,
90
151
  'The minimum percent a method must take before ',
91
152
  ' being included in output reports.',
92
- ' this option is not supported for call tree.') do |min_percent|
153
+ ' This option is not supported for call tree.') do |min_percent|
93
154
  options.min_percent = min_percent
94
155
  end
95
156
 
@@ -100,31 +161,22 @@ module RubyProf
100
161
  end
101
162
 
102
163
  opts.on('--mode=measure_mode',
103
- [:process, :wall, :cpu, :allocations, :memory, :gc_runs, :gc_time],
164
+ [:process, :wall, :allocations, :memory],
104
165
  'Select what ruby-prof should measure:',
105
166
  ' wall - Wall time (default).',
106
167
  ' process - Process time.',
107
- ' cpu - CPU time (Pentium and PowerPCs only).',
108
168
  ' allocations - Object allocations (requires patched Ruby interpreter).',
109
- ' memory - Allocated memory in KB (requires patched Ruby interpreter).',
110
- ' gc_runs - Number of garbage collections (requires patched Ruby interpreter).',
111
- ' gc_time - Time spent in garbage collection (requires patched Ruby interpreter).') do |measure_mode|
169
+ ' memory - Allocated memory in KB (requires patched Ruby interpreter).') do |measure_mode|
112
170
 
113
171
  case measure_mode
114
172
  when :wall
115
173
  options.measure_mode = RubyProf::WALL_TIME
116
174
  when :process
117
175
  options.measure_mode = RubyProf::PROCESS_TIME
118
- when :cpu
119
- options.measure_mode = RubyProf::CPU_TIME
120
176
  when :allocations
121
177
  options.measure_mode = RubyProf::ALLOCATIONS
122
178
  when :memory
123
179
  options.measure_mode = RubyProf::MEMORY
124
- when :gc_runs
125
- options.measure_mode = RubyProf::GC_RUNS
126
- when :gc_time
127
- options.measure_mode = RubyProf::GC_TIME
128
180
  end
129
181
  end
130
182
 
@@ -147,94 +199,45 @@ module RubyProf
147
199
  end
148
200
  end
149
201
 
150
- opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
151
- options.replace_prog_name = true
152
- end
153
-
154
- if defined?(RubyVM)
155
- opts.on("--specialized-instruction", "Turn on specified instruction.") do
156
- options.specialized_instruction = true
157
- end
158
- end
159
-
160
202
  opts.on_tail("-h", "--help", "Show help message") do
161
203
  puts opts
162
204
  exit
163
205
  end
164
206
 
165
- opts.on_tail("--version", "Show version #{RubyProf::VERSION}") do
207
+ opts.on_tail("-v version", "--version", "Show version (#{RubyProf::VERSION})") do
166
208
  puts "ruby_prof " + RubyProf::VERSION
167
209
  exit
168
210
  end
169
211
 
170
- opts.on("-v","Show version, set $VERBOSE to true, profile script if option given") do
171
- puts "ruby version: " + [RUBY_PATCHLEVEL, RUBY_PLATFORM, RUBY_VERSION].join(' ')
172
- $VERBOSE = true
173
- end
174
-
175
- opts.on("-d", "Set $DEBUG to true") do
176
- $DEBUG = true
212
+ opts.on('--allow_exceptions', 'Raise exceptions encountered during profiling (true) or suppress them (false)') do
213
+ options.allow_exceptions = true
177
214
  end
178
215
 
179
- opts.on('-R lib', '--require-noprof lib', 'require a specific library (not profiled)') do |lib|
216
+ opts.on('-R lib', '--require-noprof=lib', 'require a specific library (not profiled)') do |lib|
180
217
  options.pre_libs << lib
181
218
  end
182
219
 
183
- opts.on('-E code', '--eval-noprof code', 'execute the ruby statements (not profiled)') do |code|
220
+ opts.on('-E code', '--eval-noprof=code', 'execute the ruby statements (not profiled)') do |code|
184
221
  options.pre_execs << code
185
222
  end
186
223
 
187
- opts.on('-x regexp', '--exclude regexp', 'exclude methods by regexp (see method elimination)') do|meth|
188
- options.eliminate_methods ||= []
189
- options.eliminate_methods << Regexp.new(meth)
190
- end
191
-
192
- opts.on('-X file', '--exclude-file file', 'exclude methods by regexp listed in file (see method elimination)') do|file|
193
- options.eliminate_methods_files ||= []
194
- options.eliminate_methods_files << file
195
- end
196
-
197
- opts.on('--exclude-common-cycles', 'make common iterators like Integer#times appear inlined') do |meth|
198
- options.eliminate_methods ||= []
199
- options.eliminate_methods += %w{
200
- Integer#times
201
- Integer#upto
202
- Integer#downto
203
- Enumerator#each
204
- Enumerator#each_with_index
205
- Enumerator#each_with_object
206
-
207
- Array#each
208
- Array#each_index
209
- Array#reverse_each
210
- Array#map
211
-
212
- Hash#each
213
- Hash#each_pair
214
- Hash#each_key
215
- Hash#each_value
216
-
217
- Range#each
218
- Enumerable#each_cons
219
- Enumerable#each_entry
220
- Enumerable#each_slice
221
- Enumerable#each_with_index
222
- Enumerable#each_with_object
223
- Enumerable#reverse_each
224
- Enumerable#inject
225
- Enumerable#collect
226
- Enumerable#reduce
227
- }
228
- #TODO: may be the whole Enumerable module should be excluded via 'Enumerable#.*', we need feedback on use cases.
224
+ opts.on('--exclude=methods', String,
225
+ 'A comma separated list of methods to exclude.',
226
+ ' Specify instance methods via # (Integer#times)',
227
+ ' Specify class methods via . (Integer.superclass)') do |exclude_string|
228
+ exclude_string.split(',').each do |string|
229
+ match = string.strip.match(/(.*)(#|\.)(.*)/)
230
+ klass = constantize(match[1])
231
+ if match[2] == '.'
232
+ klass = klass.singleton_class
233
+ end
234
+ method = match[3].to_sym
235
+ options.exclude << [klass, method]
236
+ end
229
237
  end
230
238
 
231
- opts.on('--exclude-common-callbacks', 'make common callbacks invocations like Integer#times appear inlined so you can see call origins in graph') do|meth|
232
- options.eliminate_methods ||= []
233
- options.eliminate_methods += %w{
234
- Method#call
235
- Proc#call
236
- ActiveSupport::Callbacks::ClassMethods#__run_callback
237
- }
239
+ opts.on('--exclude-common', 'Remove common methods from the profile') do
240
+ options.exclude_common = true
238
241
  end
239
242
  end
240
243
  end
@@ -278,23 +281,15 @@ module RubyProf
278
281
  end
279
282
 
280
283
  def run
281
- # Get the script we will execute
282
284
  script = ARGV.shift
283
- if options.replace_prog_name
284
- $0 = File.expand_path(script)
285
+ @profile = Profile.new(options.to_h)
286
+ options.exclude.each do |klass, method|
287
+ @profile.exclude_method!(klass, method)
285
288
  end
286
289
 
287
- # Set VM compile option
288
- if defined?(RubyVM)
289
- RubyVM::InstructionSequence.compile_option = {
290
- :trace_instruction => true,
291
- :specialized_instruction => options.specialized_instruction
292
- }
290
+ profile.profile do
291
+ load script
293
292
  end
294
-
295
- # Set the measure mode
296
- RubyProf.measure_mode = options.measure_mode if options.measure_mode
297
- RubyProf.start_script(script)
298
293
  end
299
294
  end
300
295
  end
@@ -307,20 +302,8 @@ cmd = RubyProf::Cmd.new
307
302
  # *after* any other one that will be installed.
308
303
 
309
304
  at_exit {
310
- # Stop profiling
311
- result = RubyProf.stop
312
-
313
- # Eliminate unwanted methods from call graph
314
- if cmd.options.eliminate_methods
315
- result.eliminate_methods!(cmd.options.eliminate_methods)
316
- end
317
-
318
- if cmd.options.eliminate_methods_files
319
- cmd.options.eliminate_methods_files.each {|f| result.eliminate_methods!(f)}
320
- end
321
-
322
305
  # Create a printer
323
- printer = cmd.options.printer.new(result)
306
+ printer = cmd.options.printer.new(cmd.profile)
324
307
  printer_options = {:min_percent => cmd.options.min_percent, :sort_method => cmd.options.sort_method}
325
308
 
326
309
  # Get output
@@ -5,34 +5,16 @@ if RUBY_ENGINE != "ruby"
5
5
  exit(1)
6
6
  end
7
7
 
8
- if RUBY_VERSION < "1.9.3"
9
- STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 1.9.3 or higher. *****\n\n")
8
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4.0')
9
+ STDERR.puts("\n\n***** Ruby version #{RUBY_VERSION} is no longer supported. Please upgrade to 2.3 or higher. *****\n\n")
10
10
  exit(1)
11
11
  end
12
12
 
13
13
  # For the love of bitfields...
14
14
  $CFLAGS += ' -std=c99'
15
15
 
16
- # standard ruby methods
17
- have_func("rb_gc_stat")
18
- have_func("rb_gc_count")
19
- have_func("rb_remove_event_hook_with_data")
20
-
21
- # Alexander Dymo GC patch
22
- have_func("rb_os_allocated_objects")
23
- have_func("rb_gc_allocated_size")
24
-
25
- # Stefan Kaes GC patches
26
- have_func("rb_gc_collections")
27
- have_func("rb_gc_time")
28
- # for ruby 2.1
29
- have_func("rb_gc_total_time")
30
- have_func("rb_gc_total_mallocs")
31
- have_func("rb_gc_total_malloced_bytes")
32
-
33
- # Lloyd Hilaiel's heap info patch
34
- have_func("rb_heap_total_mem")
35
- have_func("rb_gc_heap_info")
16
+ # And since we are using C99
17
+ CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
36
18
 
37
19
  def add_define(name, value = nil)
38
20
  if value
@@ -46,23 +28,9 @@ def windows?
46
28
  RbConfig::CONFIG['host_os'] =~ /mswin|mingw/
47
29
  end
48
30
 
49
- if !windows? && RUBY_PLATFORM !~ /(darwin|openbsd)/
50
- $LDFLAGS += " -lrt" # for clock_gettime
51
- end
52
31
  add_define("RUBY_PROF_RUBY_VERSION", RUBY_VERSION.split('.')[0..2].inject(0){|v,d| v*100+d.to_i})
53
32
 
54
- # for ruby 1.9, determine whether threads inherit trace flags (latest 1.9.2 and later should work correctly)
55
- if RUBY_VERSION > "1.9"
56
- require 'set'
57
- threads = Set.new
58
- set_trace_func lambda { |*args| threads << Thread.current.object_id }
59
- Thread.new{1}.join
60
- set_trace_func nil
61
- if threads.size < 2
62
- # if we end up here, ruby does not automatically activate tracing in spawned threads
63
- STDERR.puts("Ruby #{RUBY_VERSION} does not activate tracing in spawned threads. Consider upgrading.")
64
- exit(1)
65
- end
66
- end
33
+ # This function was added in Ruby 2.5, so once Ruby 2.4 is no longer supported this can be removed
34
+ have_func('rb_tracearg_callee_id', ["ruby.h"])
67
35
 
68
36
  create_makefile("ruby_prof")
@@ -0,0 +1,41 @@
1
+ /* Copyright (C) 2005-2019 Shugo Maeda <shugo@ruby-lang.org> and Charlie Savage <cfis@savagexi.com>
2
+ Please see the LICENSE file for copyright and distribution information */
3
+
4
+ #include "rp_aggregate_call_tree.h"
5
+
6
+ VALUE cRpAggregateCallTree;
7
+
8
+ void prof_aggregate_call_tree_mark(void* data)
9
+ {
10
+ prof_call_tree_t* call_tree = (prof_call_tree_t*)data;
11
+
12
+ if (call_tree->object != Qnil)
13
+ rb_gc_mark(call_tree->object);
14
+
15
+ if (call_tree->source_file != Qnil)
16
+ rb_gc_mark(call_tree->source_file);
17
+
18
+ prof_measurement_mark(call_tree->measurement);
19
+ }
20
+
21
+ static void prof_aggregate_call_tree_ruby_gc_free(void* data)
22
+ {
23
+ prof_call_tree_t* call_tree = (prof_call_tree_t*)data;
24
+ prof_call_tree_free(call_tree);
25
+ }
26
+
27
+ VALUE prof_aggregate_call_tree_wrap(prof_call_tree_t* call_tree)
28
+ {
29
+ if (call_tree->object == Qnil)
30
+ {
31
+ call_tree->object = Data_Wrap_Struct(cRpAggregateCallTree, prof_aggregate_call_tree_mark, prof_aggregate_call_tree_ruby_gc_free, call_tree);
32
+ }
33
+ return call_tree->object;
34
+ }
35
+
36
+ void rp_init_aggregate_call_tree()
37
+ {
38
+ // AggregateCallTree
39
+ cRpAggregateCallTree = rb_define_class_under(mProf, "AggregateCallTree", cRpCallTree);
40
+ rb_undef_method(CLASS_OF(cRpAggregateCallTree), "new");
41
+ }