ruby-prof 1.8.0-x64-mswin64-140

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 (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +665 -0
  3. data/LICENSE +25 -0
  4. data/README.md +5 -0
  5. data/Rakefile +98 -0
  6. data/bin/ruby-prof +341 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +23 -0
  9. data/ext/ruby_prof/rp_allocation.c +327 -0
  10. data/ext/ruby_prof/rp_allocation.h +32 -0
  11. data/ext/ruby_prof/rp_call_tree.c +502 -0
  12. data/ext/ruby_prof/rp_call_tree.h +47 -0
  13. data/ext/ruby_prof/rp_call_trees.c +296 -0
  14. data/ext/ruby_prof/rp_call_trees.h +28 -0
  15. data/ext/ruby_prof/rp_measure_allocations.c +47 -0
  16. data/ext/ruby_prof/rp_measure_memory.c +46 -0
  17. data/ext/ruby_prof/rp_measure_process_time.c +64 -0
  18. data/ext/ruby_prof/rp_measure_wall_time.c +52 -0
  19. data/ext/ruby_prof/rp_measurement.c +359 -0
  20. data/ext/ruby_prof/rp_measurement.h +52 -0
  21. data/ext/ruby_prof/rp_method.c +551 -0
  22. data/ext/ruby_prof/rp_method.h +66 -0
  23. data/ext/ruby_prof/rp_profile.c +933 -0
  24. data/ext/ruby_prof/rp_profile.h +36 -0
  25. data/ext/ruby_prof/rp_stack.c +212 -0
  26. data/ext/ruby_prof/rp_stack.h +53 -0
  27. data/ext/ruby_prof/rp_thread.c +433 -0
  28. data/ext/ruby_prof/rp_thread.h +39 -0
  29. data/ext/ruby_prof/ruby_prof.c +50 -0
  30. data/ext/ruby_prof/ruby_prof.h +35 -0
  31. data/ext/ruby_prof/vc/ruby_prof.sln +39 -0
  32. data/ext/ruby_prof/vc/ruby_prof.vcxproj +158 -0
  33. data/lib/ruby-prof/assets/call_stack_printer.html.erb +711 -0
  34. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  35. data/lib/ruby-prof/assets/graph_printer.html.erb +355 -0
  36. data/lib/ruby-prof/call_tree.rb +57 -0
  37. data/lib/ruby-prof/call_tree_visitor.rb +36 -0
  38. data/lib/ruby-prof/compatibility.rb +113 -0
  39. data/lib/ruby-prof/exclude_common_methods.rb +204 -0
  40. data/lib/ruby-prof/measurement.rb +17 -0
  41. data/lib/ruby-prof/method_info.rb +87 -0
  42. data/lib/ruby-prof/printers/abstract_printer.rb +156 -0
  43. data/lib/ruby-prof/printers/call_info_printer.rb +53 -0
  44. data/lib/ruby-prof/printers/call_stack_printer.rb +180 -0
  45. data/lib/ruby-prof/printers/call_tree_printer.rb +145 -0
  46. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  47. data/lib/ruby-prof/printers/flat_printer.rb +53 -0
  48. data/lib/ruby-prof/printers/graph_html_printer.rb +63 -0
  49. data/lib/ruby-prof/printers/graph_printer.rb +113 -0
  50. data/lib/ruby-prof/printers/multi_printer.rb +127 -0
  51. data/lib/ruby-prof/profile.rb +70 -0
  52. data/lib/ruby-prof/rack.rb +105 -0
  53. data/lib/ruby-prof/task.rb +147 -0
  54. data/lib/ruby-prof/thread.rb +20 -0
  55. data/lib/ruby-prof/version.rb +3 -0
  56. data/lib/ruby-prof.rb +52 -0
  57. data/lib/unprof.rb +10 -0
  58. data/ruby-prof.gemspec +67 -0
  59. data/test/abstract_printer_test.rb +27 -0
  60. data/test/alias_test.rb +117 -0
  61. data/test/call_tree_builder.rb +126 -0
  62. data/test/call_tree_test.rb +94 -0
  63. data/test/call_tree_visitor_test.rb +27 -0
  64. data/test/call_trees_test.rb +66 -0
  65. data/test/compatibility_test.rb +49 -0
  66. data/test/duplicate_names_test.rb +32 -0
  67. data/test/dynamic_method_test.rb +50 -0
  68. data/test/enumerable_test.rb +23 -0
  69. data/test/exceptions_test.rb +24 -0
  70. data/test/exclude_methods_test.rb +363 -0
  71. data/test/exclude_threads_test.rb +48 -0
  72. data/test/fiber_test.rb +195 -0
  73. data/test/gc_test.rb +104 -0
  74. data/test/inverse_call_tree_test.rb +174 -0
  75. data/test/line_number_test.rb +426 -0
  76. data/test/marshal_test.rb +145 -0
  77. data/test/measure_allocations.rb +26 -0
  78. data/test/measure_allocations_test.rb +1172 -0
  79. data/test/measure_process_time_test.rb +3330 -0
  80. data/test/measure_times.rb +56 -0
  81. data/test/measure_wall_time_test.rb +635 -0
  82. data/test/measurement_test.rb +82 -0
  83. data/test/merge_test.rb +146 -0
  84. data/test/method_info_test.rb +100 -0
  85. data/test/multi_printer_test.rb +66 -0
  86. data/test/no_method_class_test.rb +15 -0
  87. data/test/pause_resume_test.rb +171 -0
  88. data/test/prime.rb +54 -0
  89. data/test/prime_script.rb +6 -0
  90. data/test/printer_call_stack_test.rb +27 -0
  91. data/test/printer_call_tree_test.rb +30 -0
  92. data/test/printer_flat_test.rb +99 -0
  93. data/test/printer_graph_html_test.rb +59 -0
  94. data/test/printer_graph_test.rb +40 -0
  95. data/test/printers_test.rb +178 -0
  96. data/test/printing_recursive_graph_test.rb +81 -0
  97. data/test/profile_test.rb +101 -0
  98. data/test/rack_test.rb +93 -0
  99. data/test/recursive_test.rb +796 -0
  100. data/test/scheduler.rb +363 -0
  101. data/test/singleton_test.rb +38 -0
  102. data/test/stack_printer_test.rb +61 -0
  103. data/test/start_stop_test.rb +106 -0
  104. data/test/test_helper.rb +21 -0
  105. data/test/thread_test.rb +229 -0
  106. data/test/unique_call_path_test.rb +123 -0
  107. data/test/yarv_test.rb +56 -0
  108. metadata +228 -0
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ # ruby-prof
2
+
3
+ ![ruby-prof](https://github.com/ruby-prof/ruby-prof/workflows/ruby-prof/badge.svg)
4
+
5
+ For an overview of ruby-prof please see https://ruby-prof.github.io
data/Rakefile ADDED
@@ -0,0 +1,98 @@
1
+ # encoding: utf-8
2
+
3
+ require "rubygems/package_task"
4
+ require "rake/extensiontask"
5
+ require "rake/testtask"
6
+ require "rdoc/task"
7
+ require "date"
8
+ require "rake/clean"
9
+
10
+ # To release a version of ruby-prof:
11
+ # * Update lib/ruby-prof/version.rb
12
+ # * Update CHANGES
13
+ # * git commit to commit files
14
+ # * rake clobber to remove extra files
15
+ # * rake compile to build windows gems
16
+ # * rake package to create the gems
17
+ # * Tag the release (git tag 0.10.1)
18
+ # * Push to ruybgems.org (gem push pkg/<gem files>)
19
+
20
+ GEM_NAME = 'ruby-prof'
21
+ SO_NAME = 'ruby_prof'
22
+
23
+ default_spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
24
+
25
+ # specify which versions/builds to cross compile
26
+ Rake::ExtensionTask.new do |ext|
27
+ ext.gem_spec = default_spec
28
+ ext.name = SO_NAME
29
+ ext.ext_dir = "ext/#{SO_NAME}"
30
+ ext.lib_dir = "lib/#{Gem::Version.new(RUBY_VERSION).segments[0..1].join('.')}"
31
+ ext.cross_compile = true
32
+ ext.cross_platform = ['x64-mingw32']
33
+ end
34
+
35
+ # Rake task to build the default package
36
+ Gem::PackageTask.new(default_spec) do |pkg|
37
+ pkg.need_tar = true
38
+ end
39
+
40
+ # make sure rdoc has been built when packaging
41
+ # why do we ship rdoc as part of the gem?
42
+ Rake::Task[:package].enhance [:rdoc]
43
+
44
+ # Setup Windows Gem
45
+ if RUBY_PLATFORM.match(/mswin|mingw/)
46
+ # Windows specification
47
+ win_spec = default_spec.clone
48
+ win_spec.platform = Gem::Platform::CURRENT
49
+ win_spec.files += Dir.glob('lib/**/*.so')
50
+
51
+ # Unset extensions
52
+ win_spec.extensions = nil
53
+
54
+ # Rake task to build the windows package
55
+ Gem::PackageTask.new(win_spec) do |pkg|
56
+ pkg.need_tar = false
57
+ end
58
+ end
59
+
60
+ # --------- RDoc Documentation ------
61
+ desc "Generate rdoc documentation"
62
+ RDoc::Task.new("rdoc") do |rdoc|
63
+ rdoc.rdoc_dir = 'doc'
64
+ rdoc.title = "ruby-prof"
65
+ # Show source inline with line numbers
66
+ rdoc.options << "--line-numbers"
67
+ # Make the readme file the start page for the generated html
68
+ rdoc.options << '--main' << 'README.md'
69
+ rdoc.rdoc_files.include('bin/*',
70
+ 'doc/*.rdoc',
71
+ 'lib/**/*.rb',
72
+ 'ext/ruby_prof/*.c',
73
+ 'ext/ruby_prof/*.h',
74
+ 'README.md',
75
+ 'LICENSE')
76
+ end
77
+
78
+ task :default => :test
79
+
80
+ for file in Dir['lib/**/*.{o,so,bundle}']
81
+ CLEAN.include file
82
+ end
83
+ for file in Dir['doc/**/*.{txt,dat,png,html}']
84
+ CLEAN.include file
85
+ end
86
+ CLEAN.reject!{|f| !File.exist?(f)}
87
+ task :clean do
88
+ # remove tmp dir contents completely after cleaning
89
+ FileUtils.rm_rf('tmp/*')
90
+ end
91
+
92
+ desc 'Run the ruby-prof test suite'
93
+ Rake::TestTask.new do |t|
94
+ t.libs += %w(lib ext test)
95
+ t.test_files = Dir['test/**_test.rb']
96
+ t.verbose = true
97
+ t.warning = true
98
+ end
data/bin/ruby-prof ADDED
@@ -0,0 +1,341 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # First require ruby-prof
4
+ require 'ruby-prof'
5
+
6
+ # Now setup option parser
7
+ require 'ostruct'
8
+ require 'optparse'
9
+
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
+ # --allow_exceptions Raise exceptions encountered during profiling (true) or suppress them (false)
20
+ # -E, --eval-noprof=code execute the ruby statements (not profiled)
21
+ # --exclude=methods A comma separated list of methods to exclude.
22
+ # Specify instance methods via # (Integer#times)
23
+ # Specify class methods via . (Integer.superclass)
24
+ # --exclude-common Remove common methods from the profile
25
+ # -f, --file=path Output results to a file instead of standard out.
26
+ # -m, --min_percent=min_percent The minimum percent a method must take before
27
+ # being included in output reports.
28
+ # This option is not supported for call tree.
29
+ # --mode=measure_mode Select what ruby-prof should measure:
30
+ # wall - Wall time (default).
31
+ # process - Process time.
32
+ # allocations - Object allocations (requires patched Ruby interpreter).
33
+ # memory - Allocated memory in KB (requires patched Ruby interpreter).
34
+ # -p, --printer=printer Select a printer:
35
+ # flat - Prints a flat profile as text (default).
36
+ # graph - Prints a graph profile as text.
37
+ # graph_html - Prints a graph profile as html.
38
+ # call_tree - format for KCacheGrind
39
+ # call_stack - prints a HTML visualization of the call tree
40
+ # dot - Prints a graph profile as a dot file
41
+ # multi - Creates several reports in output directory
42
+ # -R, --require-noprof=lib require a specific library (not profiled)
43
+ # -s, --sort=sort_mode Select how ruby-prof results should be sorted:
44
+ # total - Total time
45
+ # self - Self time
46
+ # wait - Wait time
47
+ # child - Child time
48
+ # --track_allocations Track allocations while profiling
49
+ # -v, --version version Show version (1.1.0)
50
+ # -h, --help Show help message
51
+
52
+ class Cmd
53
+ # :enddoc:
54
+ attr_accessor :options
55
+ attr_reader :profile
56
+
57
+ def initialize
58
+ setup_options
59
+ parse_args
60
+
61
+ load_pre_libs
62
+ load_pre_execs
63
+ end
64
+
65
+ def setup_options
66
+ @options = OpenStruct.new
67
+ options.allow_exceptions = false
68
+ options.exclude = Array.new
69
+ options.exclude_common = false
70
+ options.file = nil
71
+ options.measure_mode = RubyProf::WALL_TIME
72
+ options.min_percent = 0
73
+ options.pre_libs = Array.new
74
+ options.pre_execs = Array.new
75
+ options.printer = RubyProf::FlatPrinter
76
+ options.track_allocations = false
77
+ end
78
+
79
+ # This is copied from ActiveSupport:
80
+ def constantize(camel_cased_word)
81
+ if !camel_cased_word.include?("::")
82
+ Object.const_get(camel_cased_word)
83
+ else
84
+ names = camel_cased_word.split("::")
85
+
86
+ # Trigger a built-in NameError exception including the ill-formed constant in the message.
87
+ Object.const_get(camel_cased_word) if names.empty?
88
+
89
+ # Remove the first blank element in case of '::ClassName' notation.
90
+ names.shift if names.size > 1 && names.first.empty?
91
+
92
+ names.inject(Object) do |constant, name|
93
+ if constant == Object
94
+ constant.const_get(name)
95
+ else
96
+ candidate = constant.const_get(name)
97
+ next candidate if constant.const_defined?(name, false)
98
+ next candidate unless Object.const_defined?(name)
99
+
100
+ # Go down the ancestors to check if it is owned directly. The check
101
+ # stops when we reach Object or the end of ancestors tree.
102
+ constant = constant.ancestors.inject(constant) do |const, ancestor|
103
+ break const if ancestor == Object
104
+ break ancestor if ancestor.const_defined?(name, false)
105
+ const
106
+ end
107
+
108
+ # owner is in Object, so raise
109
+ constant.const_get(name, false)
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ def option_parser
116
+ OptionParser.new do |opts|
117
+ opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
118
+ "Usage: ruby-prof [options] <script.rb> [--] [profiled-script-command-line-options]"
119
+
120
+ opts.separator ""
121
+ opts.separator "Options:"
122
+
123
+ opts.on('--allow_exceptions', 'Raise exceptions encountered during profiling (true) or suppress them (false)') do
124
+ options.allow_exceptions = true
125
+ end
126
+
127
+ opts.on('-E code', '--eval-noprof=code', 'execute the ruby statements (not profiled)') do |code|
128
+ options.pre_execs << code
129
+ end
130
+
131
+ opts.on('--exclude=methods', String,
132
+ 'A comma separated list of methods to exclude.',
133
+ ' Specify instance methods via # (Integer#times)',
134
+ ' Specify class methods via . (Integer.superclass)') do |exclude_string|
135
+ exclude_string.split(',').each do |string|
136
+ match = string.strip.match(/(.*)(#|\.)(.*)/)
137
+ klass = constantize(match[1])
138
+ if match[2] == '.'
139
+ klass = klass.singleton_class
140
+ end
141
+ method = match[3].to_sym
142
+ options.exclude << [klass, method]
143
+ end
144
+ end
145
+
146
+ opts.on('--exclude-common', 'Remove common methods from the profile') do
147
+ options.exclude_common = true
148
+ end
149
+
150
+ opts.on('-f path', '--file=path',
151
+ 'Output results to a file instead of standard out.') do |file|
152
+ options.file = file
153
+ options.old_wd = Dir.pwd
154
+ end
155
+
156
+ opts.on('-m min_percent', '--min_percent=min_percent', Float,
157
+ 'The minimum percent a method must take before ',
158
+ ' being included in output reports.',
159
+ ' This option is not supported for call tree.') do |min_percent|
160
+ options.min_percent = min_percent
161
+ end
162
+
163
+ opts.on('--mode=measure_mode',
164
+ [:process, :wall, :allocations, :memory],
165
+ 'Select what ruby-prof should measure:',
166
+ ' wall - Wall time (default).',
167
+ ' process - Process time.',
168
+ ' allocations - Object allocations (requires patched Ruby interpreter).',
169
+ ' memory - Allocated memory in KB (requires patched Ruby interpreter).') do |measure_mode|
170
+
171
+ case measure_mode
172
+ when :wall
173
+ options.measure_mode = RubyProf::WALL_TIME
174
+ when :process
175
+ options.measure_mode = RubyProf::PROCESS_TIME
176
+ when :allocations
177
+ options.measure_mode = RubyProf::ALLOCATIONS
178
+ when :memory
179
+ options.measure_mode = RubyProf::MEMORY
180
+ end
181
+ end
182
+
183
+ opts.on('-p printer', '--printer=printer', [:flat, :flat_with_line_numbers, :graph, :graph_html, :call_tree, :call_stack, :dot, :multi],
184
+ 'Select a printer:',
185
+ ' flat - Prints a flat profile as text (default).',
186
+ ' graph - Prints a graph profile as text.',
187
+ ' graph_html - Prints a graph profile as html.',
188
+ ' call_tree - format for KCacheGrind',
189
+ ' call_stack - prints a HTML visualization of the call tree',
190
+ ' dot - Prints a graph profile as a dot file',
191
+ ' multi - Creates several reports in output directory'
192
+ ) do |printer|
193
+
194
+ case printer
195
+ when :flat
196
+ options.printer = RubyProf::FlatPrinter
197
+ when :graph
198
+ options.printer = RubyProf::GraphPrinter
199
+ when :graph_html
200
+ options.printer = RubyProf::GraphHtmlPrinter
201
+ when :call_tree
202
+ options.printer = RubyProf::CallTreePrinter
203
+ when :call_stack
204
+ options.printer = RubyProf::CallStackPrinter
205
+ when :dot
206
+ options.printer = RubyProf::DotPrinter
207
+ when :multi
208
+ options.printer = RubyProf::MultiPrinter
209
+ end
210
+ end
211
+
212
+ opts.on('-R lib', '--require-noprof=lib', 'require a specific library (not profiled)') do |lib|
213
+ options.pre_libs << lib
214
+ end
215
+
216
+ opts.on('-s sort_mode', '--sort=sort_mode', [:total, :self, :wait, :child],
217
+ 'Select how ruby-prof results should be sorted:',
218
+ ' total - Total time',
219
+ ' self - Self time',
220
+ ' wait - Wait time',
221
+ ' child - Child time') do |sort_mode|
222
+
223
+ options.sort_method = case sort_mode
224
+ when :total
225
+ :total_time
226
+ when :self
227
+ :self_time
228
+ when :wait
229
+ :wait_time
230
+ when :child
231
+ :children_time
232
+ end
233
+ end
234
+
235
+ opts.on('--track_allocations', 'Track allocations while profiling') do
236
+ options.track_allocations = true
237
+ end
238
+
239
+ opts.on_tail("-v version", "--version", "Show version (#{RubyProf::VERSION})") do
240
+ puts "ruby_prof " + RubyProf::VERSION
241
+ exit
242
+ end
243
+
244
+ opts.on_tail("-h", "--help", "Show help message") do
245
+ puts opts
246
+ exit
247
+ end
248
+ end
249
+ end
250
+
251
+ def parse_args
252
+ # Make sure the user specified at least one file
253
+ if ARGV.length < 1 and not options.exec
254
+ puts self.option_parser
255
+ puts ""
256
+ puts "Must specify a script to run"
257
+ exit(-1)
258
+ end
259
+
260
+ self.option_parser.parse! ARGV
261
+
262
+ if options.printer.needs_dir?
263
+ options.file ||= "."
264
+ options.old_wd ||= Dir.pwd
265
+ if !File.directory?(options.file)
266
+ puts "'#{options.file}' is not a directory"
267
+ puts "#{options.printer} needs an existing directory path to put profiles under."
268
+ exit(-1)
269
+ end
270
+ end
271
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e
272
+ puts self.option_parser
273
+ puts e.message
274
+ exit(-1)
275
+ end
276
+
277
+ def load_pre_libs
278
+ options.pre_libs.each do |lib|
279
+ require lib
280
+ end
281
+ end
282
+
283
+ def load_pre_execs
284
+ options.pre_execs.each do |exec|
285
+ eval(exec)
286
+ end
287
+ end
288
+
289
+ def run
290
+ profile_options = {:allow_exceptions => options.allow_exceptions,
291
+ :exclude_common => options.exclude_common,
292
+ :measure_mode => options.measure_mode,
293
+ :track_allocations => options.track_allocations}
294
+
295
+ @profile = Profile.new(**profile_options)
296
+
297
+ options.exclude.each do |klass, method|
298
+ @profile.exclude_method!(klass, method)
299
+ end
300
+
301
+ script = ARGV.shift
302
+ profile.profile do
303
+ load script
304
+ end
305
+ end
306
+ end
307
+ end
308
+
309
+ # Parse command line options
310
+ cmd = RubyProf::Cmd.new
311
+
312
+ # Install at_exit handler. It is important that we do this
313
+ # before loading the scripts so our at_exit handler run
314
+ # *after* any other one that will be installed.
315
+
316
+ at_exit {
317
+ # Create a printer
318
+ printer = cmd.options.printer.new(cmd.profile)
319
+ printer_options = {:min_percent => cmd.options.min_percent,
320
+ :sort_method => cmd.options.sort_method}
321
+
322
+ # Get output
323
+ if cmd.options.file
324
+ # write it relative to the dir they *started* in, as it's a bit surprising to write it in the dir they end up in.
325
+ Dir.chdir(cmd.options.old_wd) do
326
+ if printer.class.needs_dir?
327
+ printer.print(printer_options.merge(:path => cmd.options.file))
328
+ else
329
+ File.open(cmd.options.file, 'w') do |file|
330
+ printer.print(file, printer_options)
331
+ end
332
+ end
333
+ end
334
+ else
335
+ # Print out results
336
+ printer.print(STDOUT, printer_options)
337
+ end
338
+ }
339
+
340
+ # Now profile some code
341
+ cmd.run
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ stacks = Hash.new{|h,k| h[k] = Hash.new{|h,k| h[k] = []}}
4
+ i = 0
5
+ File.open(ARGV[0]).each_line do |l|
6
+ i += 1
7
+ unless l =~ /^(\d+):(\d+): *\d+ms *([^ ]+) *(.*): *(\d+) *(.+)$/
8
+ next if l =~/^ *$/
9
+ puts "line doesn't match: #{l}"
10
+ next
11
+ end
12
+ details = $1.to_i, $2.to_i, $3, $4, $5.to_i, $6
13
+ thread, fiber, event, file, line, method = *details
14
+ # puts method
15
+ stack = stacks[thread][fiber]
16
+ case event
17
+ when 'call', 'c-call'
18
+ stack << method
19
+ when 'return', 'c-return'
20
+ last_method = stack.pop
21
+ if last_method != method
22
+ puts "LINE #{i}: return event without call: #{method}"
23
+ puts "STACK: #{stack.inspect}"
24
+ if stack.find(method)
25
+ puts "fixing stack"
26
+ while (popped = stack.pop) && (popped != method)
27
+ puts "popped #{popped}"
28
+ end
29
+ else
30
+ raise "stack unfixable"
31
+ end
32
+ # stack << last_method
33
+ end
34
+ when 'line'
35
+ last_method = stack[-1]
36
+ if last_method != method
37
+ unless stack.find(method)
38
+ raise "LINE #{i}: line event without call: #{method}"
39
+ end
40
+ end
41
+ else
42
+ puts "unkown event"
43
+ end
44
+ end
45
+ puts stacks.inspect
@@ -0,0 +1,23 @@
1
+ require "mkmf"
2
+
3
+ # Let's go with a modern version of C! want to intermix declarations and code (ie, don't define
4
+ # all variables at the top of the method). If using Visual Studio, you'll need 2019 version
5
+ # 16.8 or higher
6
+ if RUBY_PLATFORM =~ /mswin/
7
+ $CFLAGS += ' /std:c11'
8
+ else
9
+ # Need -D_POSIX_C_SOURCE=199309L for clock_gettime
10
+ $CFLAGS += ' -std=c11 -D_POSIX_C_SOURCE=199309L'
11
+ end
12
+
13
+ # For gcc add -s to strip symbols, reducing library size from 17MB to 78KB (at least on Windows with mingw64)
14
+ if RUBY_PLATFORM !~ /mswin/
15
+ $LDFLAGS += ' -s'
16
+ end
17
+
18
+ # And since we are using C99 we want to disable Ruby sending these warnings to gcc
19
+ if CONFIG['warnflags']
20
+ CONFIG['warnflags'].gsub!('-Wdeclaration-after-statement', '')
21
+ end
22
+
23
+ create_makefile("ruby_prof")