ruby-prof 1.0.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 (97) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +523 -0
  3. data/LICENSE +25 -0
  4. data/README.rdoc +5 -0
  5. data/Rakefile +110 -0
  6. data/bin/ruby-prof +380 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/ext/ruby_prof/extconf.rb +36 -0
  9. data/ext/ruby_prof/rp_allocation.c +292 -0
  10. data/ext/ruby_prof/rp_allocation.h +31 -0
  11. data/ext/ruby_prof/rp_call_info.c +283 -0
  12. data/ext/ruby_prof/rp_call_info.h +35 -0
  13. data/ext/ruby_prof/rp_measure_allocations.c +52 -0
  14. data/ext/ruby_prof/rp_measure_memory.c +42 -0
  15. data/ext/ruby_prof/rp_measure_process_time.c +63 -0
  16. data/ext/ruby_prof/rp_measure_wall_time.c +62 -0
  17. data/ext/ruby_prof/rp_measurement.c +236 -0
  18. data/ext/ruby_prof/rp_measurement.h +49 -0
  19. data/ext/ruby_prof/rp_method.c +642 -0
  20. data/ext/ruby_prof/rp_method.h +70 -0
  21. data/ext/ruby_prof/rp_profile.c +881 -0
  22. data/ext/ruby_prof/rp_profile.h +36 -0
  23. data/ext/ruby_prof/rp_stack.c +196 -0
  24. data/ext/ruby_prof/rp_stack.h +56 -0
  25. data/ext/ruby_prof/rp_thread.c +338 -0
  26. data/ext/ruby_prof/rp_thread.h +36 -0
  27. data/ext/ruby_prof/ruby_prof.c +48 -0
  28. data/ext/ruby_prof/ruby_prof.h +17 -0
  29. data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
  30. data/ext/ruby_prof/vc/ruby_prof.vcxproj +143 -0
  31. data/lib/ruby-prof.rb +53 -0
  32. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  33. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  34. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  35. data/lib/ruby-prof/assets/graph_printer.html.erb +356 -0
  36. data/lib/ruby-prof/call_info.rb +57 -0
  37. data/lib/ruby-prof/call_info_visitor.rb +38 -0
  38. data/lib/ruby-prof/compatibility.rb +109 -0
  39. data/lib/ruby-prof/exclude_common_methods.rb +198 -0
  40. data/lib/ruby-prof/measurement.rb +14 -0
  41. data/lib/ruby-prof/method_info.rb +90 -0
  42. data/lib/ruby-prof/printers/abstract_printer.rb +118 -0
  43. data/lib/ruby-prof/printers/call_info_printer.rb +51 -0
  44. data/lib/ruby-prof/printers/call_stack_printer.rb +269 -0
  45. data/lib/ruby-prof/printers/call_tree_printer.rb +151 -0
  46. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  47. data/lib/ruby-prof/printers/flat_printer.rb +52 -0
  48. data/lib/ruby-prof/printers/graph_html_printer.rb +64 -0
  49. data/lib/ruby-prof/printers/graph_printer.rb +114 -0
  50. data/lib/ruby-prof/printers/multi_printer.rb +127 -0
  51. data/lib/ruby-prof/profile.rb +33 -0
  52. data/lib/ruby-prof/rack.rb +171 -0
  53. data/lib/ruby-prof/task.rb +147 -0
  54. data/lib/ruby-prof/thread.rb +35 -0
  55. data/lib/ruby-prof/version.rb +3 -0
  56. data/lib/unprof.rb +10 -0
  57. data/ruby-prof.gemspec +58 -0
  58. data/test/abstract_printer_test.rb +26 -0
  59. data/test/alias_test.rb +129 -0
  60. data/test/basic_test.rb +129 -0
  61. data/test/call_info_visitor_test.rb +31 -0
  62. data/test/duplicate_names_test.rb +32 -0
  63. data/test/dynamic_method_test.rb +53 -0
  64. data/test/enumerable_test.rb +21 -0
  65. data/test/exceptions_test.rb +24 -0
  66. data/test/exclude_methods_test.rb +146 -0
  67. data/test/exclude_threads_test.rb +53 -0
  68. data/test/line_number_test.rb +161 -0
  69. data/test/marshal_test.rb +119 -0
  70. data/test/measure_allocations.rb +30 -0
  71. data/test/measure_allocations_test.rb +385 -0
  72. data/test/measure_allocations_trace_test.rb +385 -0
  73. data/test/measure_memory_trace_test.rb +756 -0
  74. data/test/measure_process_time_test.rb +849 -0
  75. data/test/measure_times.rb +54 -0
  76. data/test/measure_wall_time_test.rb +459 -0
  77. data/test/multi_printer_test.rb +71 -0
  78. data/test/no_method_class_test.rb +15 -0
  79. data/test/parser_timings.rb +24 -0
  80. data/test/pause_resume_test.rb +166 -0
  81. data/test/prime.rb +56 -0
  82. data/test/printer_call_tree_test.rb +31 -0
  83. data/test/printer_flat_test.rb +68 -0
  84. data/test/printer_graph_html_test.rb +60 -0
  85. data/test/printer_graph_test.rb +41 -0
  86. data/test/printers_test.rb +141 -0
  87. data/test/printing_recursive_graph_test.rb +81 -0
  88. data/test/rack_test.rb +157 -0
  89. data/test/recursive_test.rb +210 -0
  90. data/test/singleton_test.rb +38 -0
  91. data/test/stack_printer_test.rb +64 -0
  92. data/test/start_stop_test.rb +109 -0
  93. data/test/test_helper.rb +24 -0
  94. data/test/thread_test.rb +144 -0
  95. data/test/unique_call_path_test.rb +190 -0
  96. data/test/yarv_test.rb +56 -0
  97. metadata +189 -0
data/LICENSE ADDED
@@ -0,0 +1,25 @@
1
+ Copyright (C) 2005 - 2019 Shugo Maeda <shugo@ruby-lang.org>, Charlie Savage <cfis@savagexi.com> and
2
+ Stefan Kaes <skaes@railsepxress.de>
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
16
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
+ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
19
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
+ SUCH DAMAGE.
@@ -0,0 +1,5 @@
1
+ = ruby-prof
2
+
3
+ {<img src="https://travis-ci.org/ruby-prof/ruby-prof.png?branch=master" alt="Build Status" />}[https://travis-ci.org/ruby-prof/ruby-prof]
4
+
5
+ For an overview of ruby-prof please see https://ruby-prof.github.io
@@ -0,0 +1,110 @@
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
+ begin
10
+ require "bundler/setup"
11
+ Bundler::GemHelper.install_tasks
12
+ [:build, :install, :release].each {|t| Rake::Task[t].enhance [:rdoc] }
13
+ rescue LoadError
14
+ $stderr.puts "Install bundler to get support for simplified gem publishing"
15
+ end
16
+
17
+ # To release a version of ruby-prof:
18
+ # * Update lib/ruby-prof/version.rb
19
+ # * Update CHANGES
20
+ # * git commit to commit files
21
+ # * rake clobber to remove extra files
22
+ # * rake compile to build windows gems
23
+ # * rake package to create the gems
24
+ # * Tag the release (git tag 0.10.1)
25
+ # * Push to ruybgems.org (gem push pkg/<gem files>)
26
+ # For a ruby only release, just run
27
+ # * rake release
28
+ # it will push changes to github, tag the release, build the package and upload it to rubygems.org
29
+ # and in case you forgot to increment the version number or have uncommitted changes, it will refuse to work
30
+
31
+ GEM_NAME = 'ruby-prof'
32
+ SO_NAME = 'ruby_prof'
33
+
34
+ default_spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
35
+
36
+ # specify which versions/builds to cross compile
37
+ Rake::ExtensionTask.new do |ext|
38
+ ext.gem_spec = default_spec
39
+ ext.name = SO_NAME
40
+ ext.ext_dir = "ext/#{SO_NAME}"
41
+ ext.lib_dir = "lib/#{RUBY_VERSION}"
42
+ ext.cross_compile = true
43
+ ext.cross_platform = ['x86-mingw32', 'x64-mingw32']
44
+ end
45
+
46
+ # Rake task to build the default package
47
+ Gem::PackageTask.new(default_spec) do |pkg|
48
+ pkg.need_tar = true
49
+ end
50
+
51
+ # make sure rdoc has been built when packaging
52
+ # why do we ship rdoc as part of the gem?
53
+ Rake::Task[:package].enhance [:rdoc]
54
+
55
+ # Setup Windows Gem
56
+ if RUBY_PLATFORM.match(/win32|mingw32/)
57
+ # Windows specification
58
+ win_spec = default_spec.clone
59
+ win_spec.platform = Gem::Platform::CURRENT
60
+ win_spec.files += Dir.glob('lib/**/*.so')
61
+ win_spec.instance_variable_set(:@cache_file, nil) # Hack to work around gem issue
62
+
63
+ # Unset extensions
64
+ win_spec.extensions = nil
65
+
66
+ # Rake task to build the windows package
67
+ Gem::PackageTask.new(win_spec) do |pkg|
68
+ pkg.need_tar = false
69
+ end
70
+ end
71
+
72
+ # --------- RDoc Documentation ------
73
+ desc "Generate rdoc documentation"
74
+ RDoc::Task.new("rdoc") do |rdoc|
75
+ rdoc.rdoc_dir = 'doc'
76
+ rdoc.title = "ruby-prof"
77
+ # Show source inline with line numbers
78
+ rdoc.options << "--line-numbers"
79
+ # Make the readme file the start page for the generated html
80
+ rdoc.options << '--main' << 'README.rdoc'
81
+ rdoc.rdoc_files.include('bin/*',
82
+ 'doc/*.rdoc',
83
+ 'lib/**/*.rb',
84
+ 'ext/ruby_prof/*.c',
85
+ 'ext/ruby_prof/*.h',
86
+ 'README.rdoc',
87
+ 'LICENSE')
88
+ end
89
+
90
+ task :default => :test
91
+
92
+ for file in Dir['lib/**/*.{o,so,bundle}']
93
+ CLEAN.include file
94
+ end
95
+ for file in Dir['doc/**/*.{txt,dat,png,html}']
96
+ CLEAN.include file
97
+ end
98
+ CLEAN.reject!{|f| !File.exist?(f)}
99
+ task :clean do
100
+ # remove tmp dir contents completely after cleaning
101
+ FileUtils.rm_rf('tmp/*')
102
+ end
103
+
104
+ desc 'Run the ruby-prof test suite'
105
+ Rake::TestTask.new do |t|
106
+ t.libs += %w(lib ext test)
107
+ t.test_files = Dir['test/**_test.rb']
108
+ t.verbose = true
109
+ t.warning = true
110
+ end
@@ -0,0 +1,380 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ # First require ruby-prof
4
+ require 'rubygems'
5
+ require 'ruby-prof'
6
+
7
+ # Now setup option parser
8
+ require 'ostruct'
9
+ require 'optparse'
10
+
11
+ module RubyProf
12
+ # == Synopsis
13
+ #
14
+ # Profiles a Ruby program.
15
+ #
16
+ # == Usage
17
+ #
18
+ # ruby_prof [options] <script.rb> [--] [script-options]
19
+ #
20
+ # Options:
21
+ # -p, --printer=printer Select a printer:
22
+ # flat - Prints a flat profile as text (default).
23
+ # graph - Prints a graph profile as text.
24
+ # graph_html - Prints a graph profile as html.
25
+ # call_tree - format for KCacheGrind
26
+ # call_stack - prints a HTML visualization of the call tree
27
+ # dot - Prints a graph profile as a dot file
28
+ # multi - Creates several reports in output directory
29
+ #
30
+ # -m, --min_percent=min_percent The minimum percent a method must take before
31
+ # being included in output reports. This option is not supported for call tree reports.
32
+ #
33
+ # -f, --file=path Output results to a file instead of standard out.
34
+ #
35
+ # --mode=measure_mode Select what ruby-prof should measure:
36
+ # wall - Wall time (default)
37
+ # process - Process time
38
+ # allocations - Object allocations
39
+ # memory - Allocated memory
40
+ #
41
+ # -s, --sort=sort_mode Select how ruby-prof results should be sorted:
42
+ # total - Total time
43
+ # self - Self time
44
+ # wait - Wait time
45
+ # child - Child time
46
+ #
47
+ # --replace-progname Replace $0 when loading the .rb files.
48
+ #
49
+ # --specialized-instruction Turn on specified instruction.
50
+ #
51
+ # -v Show version, set $VERBOSE to true, profile script if option given
52
+ #
53
+ # -d Set $DEBUG to true
54
+ #
55
+ # -R, --require-noprof lib Require a specific library (not profiled)
56
+ #
57
+ # -E, --eval-noprof code Execute the ruby statements (not profiled)
58
+ #
59
+ # -x, --exclude regexp Exclude methods by regexp (see method elimination)
60
+ #
61
+ # -X, --exclude-file file Exclude methods by regexp listed in file (see method elimination)
62
+ #
63
+ # --exclude-common-cycles Make common iterators like Integer#times appear inlined
64
+ #
65
+ # --exclude-common-callbacks Make common callbacks invocations like Integer#times appear inlined so you can see call origins in graph
66
+ #
67
+ # -h, --help Show help message
68
+ #
69
+ # --version Show version
70
+ #
71
+ #
72
+ class Cmd
73
+ # :enddoc:
74
+ attr_accessor :options
75
+
76
+ def initialize
77
+ setup_options
78
+ parse_args
79
+
80
+ load_pre_libs
81
+ load_pre_execs
82
+ end
83
+
84
+ def setup_options
85
+ @options = OpenStruct.new
86
+ options.printer = RubyProf::FlatPrinter
87
+ options.min_percent = 0
88
+ options.file = nil
89
+ options.replace_prog_name = false
90
+ options.specialized_instruction = false
91
+
92
+ options.pre_libs = Array.new
93
+ options.pre_execs = Array.new
94
+ end
95
+
96
+ def option_parser
97
+ OptionParser.new do |opts|
98
+ opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
99
+ "Usage: ruby-prof [options] <script.rb> [--] [profiled-script-command-line-options]"
100
+
101
+ opts.separator ""
102
+ opts.separator "Options:"
103
+
104
+ opts.on('-p printer', '--printer=printer', [:flat, :flat_with_line_numbers, :graph, :graph_html, :call_tree, :call_stack, :dot, :multi],
105
+ 'Select a printer:',
106
+ ' flat - Prints a flat profile as text (default).',
107
+ ' graph - Prints a graph profile as text.',
108
+ ' graph_html - Prints a graph profile as html.',
109
+ ' call_tree - format for KCacheGrind',
110
+ ' call_stack - prints a HTML visualization of the call tree',
111
+ ' dot - Prints a graph profile as a dot file',
112
+ ' multi - Creates several reports in output directory'
113
+ ) do |printer|
114
+
115
+ case printer
116
+ when :flat
117
+ options.printer = RubyProf::FlatPrinter
118
+ when :graph
119
+ options.printer = RubyProf::GraphPrinter
120
+ when :graph_html
121
+ options.printer = RubyProf::GraphHtmlPrinter
122
+ when :call_tree
123
+ options.printer = RubyProf::CallTreePrinter
124
+ when :call_stack
125
+ options.printer = RubyProf::CallStackPrinter
126
+ when :dot
127
+ options.printer = RubyProf::DotPrinter
128
+ when :multi
129
+ options.printer = RubyProf::MultiPrinter
130
+ end
131
+ end
132
+
133
+ opts.on('-m min_percent', '--min_percent=min_percent', Float,
134
+ 'The minimum percent a method must take before ',
135
+ ' being included in output reports.',
136
+ ' This option is not supported for call tree.') do |min_percent|
137
+ options.min_percent = min_percent
138
+ end
139
+
140
+ opts.on('-f path', '--file=path',
141
+ 'Output results to a file instead of standard out.') do |file|
142
+ options.file = file
143
+ options.old_wd = Dir.pwd
144
+ end
145
+
146
+ opts.on('--mode=measure_mode',
147
+ [:process, :wall, :allocations, :memory],
148
+ 'Select what ruby-prof should measure:',
149
+ ' wall - Wall time (default).',
150
+ ' process - Process time.',
151
+ ' allocations - Object allocations (requires patched Ruby interpreter).',
152
+ ' memory - Allocated memory in KB (requires patched Ruby interpreter).') do |measure_mode|
153
+
154
+ case measure_mode
155
+ when :wall
156
+ options.measure_mode = RubyProf::WALL_TIME
157
+ when :process
158
+ options.measure_mode = RubyProf::PROCESS_TIME
159
+ when :allocations
160
+ options.measure_mode = RubyProf::ALLOCATIONS
161
+ when :memory
162
+ options.measure_mode = RubyProf::MEMORY
163
+ end
164
+ end
165
+
166
+ opts.on('-s sort_mode', '--sort=sort_mode', [:total, :self, :wait, :child],
167
+ 'Select how ruby-prof results should be sorted:',
168
+ ' total - Total time',
169
+ ' self - Self time',
170
+ ' wait - Wait time',
171
+ ' child - Child time') do |sort_mode|
172
+
173
+ options.sort_method = case sort_mode
174
+ when :total
175
+ :total_time
176
+ when :self
177
+ :self_time
178
+ when :wait
179
+ :wait_time
180
+ when :child
181
+ :children_time
182
+ end
183
+ end
184
+
185
+ opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
186
+ options.replace_prog_name = true
187
+ end
188
+
189
+ if defined?(RubyVM)
190
+ opts.on("--specialized-instruction", "Turn on specified instruction.") do
191
+ options.specialized_instruction = true
192
+ end
193
+ end
194
+
195
+ opts.on_tail("-h", "--help", "Show help message") do
196
+ puts opts
197
+ exit
198
+ end
199
+
200
+ opts.on_tail("--version", "Show version #{RubyProf::VERSION}") do
201
+ puts "ruby_prof " + RubyProf::VERSION
202
+ exit
203
+ end
204
+
205
+ opts.on("-v","Show version, set $VERBOSE to true, profile script if option given") do
206
+ puts "ruby version: " + [RUBY_PATCHLEVEL, RUBY_PLATFORM, RUBY_VERSION].join(' ')
207
+ $VERBOSE = true
208
+ end
209
+
210
+ opts.on("-d", "Set $DEBUG to true") do
211
+ $DEBUG = true
212
+ end
213
+
214
+ opts.on('-R lib', '--require-noprof lib', 'require a specific library (not profiled)') do |lib|
215
+ options.pre_libs << lib
216
+ end
217
+
218
+ opts.on('-E code', '--eval-noprof code', 'execute the ruby statements (not profiled)') do |code|
219
+ options.pre_execs << code
220
+ end
221
+
222
+ opts.on('-x regexp', '--exclude regexp', 'exclude methods by regexp (see method elimination)') do |meth|
223
+ options.eliminate_methods ||= []
224
+ options.eliminate_methods << Regexp.new(meth)
225
+ end
226
+
227
+ opts.on('-X file', '--exclude-file file', 'exclude methods by regexp listed in file (see method elimination)') do|file|
228
+ options.eliminate_methods_files ||= []
229
+ options.eliminate_methods_files << file
230
+ end
231
+
232
+ opts.on('--exclude-common-cycles', 'make common iterators like Integer#times appear inlined') do |meth|
233
+ options.eliminate_methods ||= []
234
+ options.eliminate_methods += %w{
235
+ Integer#times
236
+ Integer#upto
237
+ Integer#downto
238
+ Enumerator#each
239
+ Enumerator#each_with_index
240
+ Enumerator#each_with_object
241
+
242
+ Array#each
243
+ Array#each_index
244
+ Array#reverse_each
245
+ Array#map
246
+
247
+ Hash#each
248
+ Hash#each_pair
249
+ Hash#each_key
250
+ Hash#each_value
251
+
252
+ Range#each
253
+ Enumerable#each_cons
254
+ Enumerable#each_entry
255
+ Enumerable#each_slice
256
+ Enumerable#each_with_index
257
+ Enumerable#each_with_object
258
+ Enumerable#reverse_each
259
+ Enumerable#inject
260
+ Enumerable#collect
261
+ Enumerable#reduce
262
+ }
263
+ #TODO: may be the whole Enumerable module should be excluded via 'Enumerable#.*', we need feedback on use cases.
264
+ end
265
+
266
+ opts.on('--exclude-common-callbacks', 'make common callbacks invocations like Integer#times appear inlined so you can see call origins in graph') do|meth|
267
+ options.eliminate_methods ||= []
268
+ options.eliminate_methods += %w{
269
+ Method#call
270
+ Proc#call
271
+ ActiveSupport::Callbacks::ClassMethods#__run_callback
272
+ }
273
+ end
274
+ end
275
+ end
276
+
277
+ def parse_args
278
+ # Make sure the user specified at least one file
279
+ if ARGV.length < 1 and not options.exec
280
+ puts self.option_parser
281
+ puts ""
282
+ puts "Must specify a script to run"
283
+ exit(-1)
284
+ end
285
+
286
+ self.option_parser.parse! ARGV
287
+
288
+ if options.printer.needs_dir?
289
+ options.file ||= "."
290
+ options.old_wd ||= Dir.pwd
291
+ if !File.directory?(options.file)
292
+ puts "'#{options.file}' is not a directory"
293
+ puts "#{options.printer} needs an existing directory path to put profiles under."
294
+ exit(-1)
295
+ end
296
+ end
297
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e
298
+ puts self.option_parser
299
+ puts e.message
300
+ exit(-1)
301
+ end
302
+
303
+ def load_pre_libs
304
+ options.pre_libs.each do |lib|
305
+ require lib
306
+ end
307
+ end
308
+
309
+ def load_pre_execs
310
+ options.pre_execs.each do |exec|
311
+ eval(exec)
312
+ end
313
+ end
314
+
315
+ def run
316
+ # Get the script we will execute
317
+ script = ARGV.shift
318
+ if options.replace_prog_name
319
+ $0 = File.expand_path(script)
320
+ end
321
+
322
+ # Set VM compile option
323
+ if defined?(RubyVM)
324
+ RubyVM::InstructionSequence.compile_option = {
325
+ :trace_instruction => true,
326
+ :specialized_instruction => options.specialized_instruction
327
+ }
328
+ end
329
+
330
+ # Set the measure mode
331
+ RubyProf.measure_mode = options.measure_mode if options.measure_mode
332
+ RubyProf.start_script(script)
333
+ end
334
+ end
335
+ end
336
+
337
+ # Parse command line options
338
+ cmd = RubyProf::Cmd.new
339
+
340
+ # Install at_exit handler. It is important that we do this
341
+ # before loading the scripts so our at_exit handler run
342
+ # *after* any other one that will be installed.
343
+
344
+ at_exit {
345
+ # Stop profiling
346
+ result = RubyProf.stop
347
+
348
+ # Eliminate unwanted methods from call graph
349
+ if cmd.options.eliminate_methods
350
+ result.eliminate_methods!(cmd.options.eliminate_methods)
351
+ end
352
+
353
+ if cmd.options.eliminate_methods_files
354
+ cmd.options.eliminate_methods_files.each {|f| result.eliminate_methods!(f)}
355
+ end
356
+
357
+ # Create a printer
358
+ printer = cmd.options.printer.new(result)
359
+ printer_options = {:min_percent => cmd.options.min_percent, :sort_method => cmd.options.sort_method}
360
+
361
+ # Get output
362
+ if cmd.options.file
363
+ # 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.
364
+ Dir.chdir(cmd.options.old_wd) do
365
+ if printer.class.needs_dir?
366
+ printer.print(printer_options.merge(:path => cmd.options.file))
367
+ else
368
+ File.open(cmd.options.file, 'w') do |file|
369
+ printer.print(file, printer_options)
370
+ end
371
+ end
372
+ end
373
+ else
374
+ # Print out results
375
+ printer.print(STDOUT, printer_options)
376
+ end
377
+ }
378
+
379
+ # Now profile some code
380
+ cmd.run