ruby-prof 0.18.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGES +500 -0
  3. data/LICENSE +25 -0
  4. data/README.rdoc +487 -0
  5. data/Rakefile +113 -0
  6. data/bin/ruby-prof +345 -0
  7. data/bin/ruby-prof-check-trace +45 -0
  8. data/examples/flat.txt +50 -0
  9. data/examples/graph.dot +84 -0
  10. data/examples/graph.html +823 -0
  11. data/examples/graph.txt +139 -0
  12. data/examples/multi.flat.txt +23 -0
  13. data/examples/multi.graph.html +760 -0
  14. data/examples/multi.grind.dat +114 -0
  15. data/examples/multi.stack.html +547 -0
  16. data/examples/stack.html +547 -0
  17. data/ext/ruby_prof/extconf.rb +68 -0
  18. data/ext/ruby_prof/rp_call_info.c +425 -0
  19. data/ext/ruby_prof/rp_call_info.h +53 -0
  20. data/ext/ruby_prof/rp_measure.c +40 -0
  21. data/ext/ruby_prof/rp_measure.h +45 -0
  22. data/ext/ruby_prof/rp_measure_allocations.c +76 -0
  23. data/ext/ruby_prof/rp_measure_cpu_time.c +136 -0
  24. data/ext/ruby_prof/rp_measure_gc_runs.c +73 -0
  25. data/ext/ruby_prof/rp_measure_gc_time.c +60 -0
  26. data/ext/ruby_prof/rp_measure_memory.c +77 -0
  27. data/ext/ruby_prof/rp_measure_process_time.c +71 -0
  28. data/ext/ruby_prof/rp_measure_wall_time.c +45 -0
  29. data/ext/ruby_prof/rp_method.c +630 -0
  30. data/ext/ruby_prof/rp_method.h +75 -0
  31. data/ext/ruby_prof/rp_stack.c +173 -0
  32. data/ext/ruby_prof/rp_stack.h +63 -0
  33. data/ext/ruby_prof/rp_thread.c +277 -0
  34. data/ext/ruby_prof/rp_thread.h +27 -0
  35. data/ext/ruby_prof/ruby_prof.c +794 -0
  36. data/ext/ruby_prof/ruby_prof.h +60 -0
  37. data/ext/ruby_prof/vc/ruby_prof.sln +31 -0
  38. data/ext/ruby_prof/vc/ruby_prof.vcxproj +141 -0
  39. data/lib/2.6.3/ruby_prof.so +0 -0
  40. data/lib/ruby-prof.rb +68 -0
  41. data/lib/ruby-prof/aggregate_call_info.rb +76 -0
  42. data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
  43. data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
  44. data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
  45. data/lib/ruby-prof/call_info.rb +115 -0
  46. data/lib/ruby-prof/call_info_visitor.rb +40 -0
  47. data/lib/ruby-prof/compatibility.rb +179 -0
  48. data/lib/ruby-prof/method_info.rb +121 -0
  49. data/lib/ruby-prof/printers/abstract_printer.rb +104 -0
  50. data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
  51. data/lib/ruby-prof/printers/call_stack_printer.rb +265 -0
  52. data/lib/ruby-prof/printers/call_tree_printer.rb +143 -0
  53. data/lib/ruby-prof/printers/dot_printer.rb +132 -0
  54. data/lib/ruby-prof/printers/flat_printer.rb +70 -0
  55. data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +83 -0
  56. data/lib/ruby-prof/printers/graph_html_printer.rb +249 -0
  57. data/lib/ruby-prof/printers/graph_printer.rb +116 -0
  58. data/lib/ruby-prof/printers/multi_printer.rb +84 -0
  59. data/lib/ruby-prof/profile.rb +26 -0
  60. data/lib/ruby-prof/profile/exclude_common_methods.rb +207 -0
  61. data/lib/ruby-prof/profile/legacy_method_elimination.rb +50 -0
  62. data/lib/ruby-prof/rack.rb +174 -0
  63. data/lib/ruby-prof/task.rb +147 -0
  64. data/lib/ruby-prof/thread.rb +35 -0
  65. data/lib/ruby-prof/version.rb +3 -0
  66. data/lib/unprof.rb +10 -0
  67. data/ruby-prof.gemspec +58 -0
  68. data/test/abstract_printer_test.rb +53 -0
  69. data/test/aggregate_test.rb +136 -0
  70. data/test/basic_test.rb +128 -0
  71. data/test/block_test.rb +74 -0
  72. data/test/call_info_test.rb +78 -0
  73. data/test/call_info_visitor_test.rb +31 -0
  74. data/test/duplicate_names_test.rb +32 -0
  75. data/test/dynamic_method_test.rb +55 -0
  76. data/test/enumerable_test.rb +21 -0
  77. data/test/exceptions_test.rb +24 -0
  78. data/test/exclude_methods_test.rb +146 -0
  79. data/test/exclude_threads_test.rb +53 -0
  80. data/test/fiber_test.rb +79 -0
  81. data/test/issue137_test.rb +63 -0
  82. data/test/line_number_test.rb +80 -0
  83. data/test/measure_allocations_test.rb +26 -0
  84. data/test/measure_cpu_time_test.rb +212 -0
  85. data/test/measure_gc_runs_test.rb +32 -0
  86. data/test/measure_gc_time_test.rb +36 -0
  87. data/test/measure_memory_test.rb +33 -0
  88. data/test/measure_process_time_test.rb +61 -0
  89. data/test/measure_wall_time_test.rb +255 -0
  90. data/test/method_elimination_test.rb +84 -0
  91. data/test/module_test.rb +45 -0
  92. data/test/multi_printer_test.rb +104 -0
  93. data/test/no_method_class_test.rb +15 -0
  94. data/test/pause_resume_test.rb +166 -0
  95. data/test/prime.rb +54 -0
  96. data/test/printers_test.rb +275 -0
  97. data/test/printing_recursive_graph_test.rb +127 -0
  98. data/test/rack_test.rb +157 -0
  99. data/test/recursive_test.rb +215 -0
  100. data/test/singleton_test.rb +38 -0
  101. data/test/stack_printer_test.rb +77 -0
  102. data/test/stack_test.rb +138 -0
  103. data/test/start_stop_test.rb +112 -0
  104. data/test/test_helper.rb +267 -0
  105. data/test/thread_test.rb +187 -0
  106. data/test/unique_call_path_test.rb +202 -0
  107. data/test/yarv_test.rb +55 -0
  108. metadata +199 -0
data/Rakefile ADDED
@@ -0,0 +1,113 @@
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-mswin32-60', 'x86-mingw32-60']
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
+ 'examples/flat.txt',
84
+ 'examples/graph.txt',
85
+ 'examples/graph.html',
86
+ 'lib/**/*.rb',
87
+ 'ext/ruby_prof/ruby_prof.c',
88
+ 'ext/ruby_prof/measure_*.h',
89
+ 'README.rdoc',
90
+ 'LICENSE')
91
+ end
92
+
93
+ task :default => :test
94
+
95
+ for file in Dir['lib/**/*.{o,so,bundle}']
96
+ CLEAN.include file
97
+ end
98
+ for file in Dir['doc/**/*.{txt,dat,png,html}']
99
+ CLEAN.include file
100
+ end
101
+ CLEAN.reject!{|f| !File.exist?(f)}
102
+ task :clean do
103
+ # remove tmp dir contents completely after cleaning
104
+ FileUtils.rm_rf('tmp/*')
105
+ end
106
+
107
+ desc 'Run the ruby-prof test suite'
108
+ Rake::TestTask.new do |t|
109
+ t.libs += %w(lib ext test)
110
+ t.test_files = Dir['test/**_test.rb']
111
+ t.verbose = true
112
+ t.warning = true
113
+ end
data/bin/ruby-prof ADDED
@@ -0,0 +1,345 @@
1
+ #! /usr/bin/env ruby
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
+ # First require ruby-prof
17
+ require 'rubygems'
18
+ require 'ruby-prof'
19
+
20
+ # Now setup option parser
21
+ require 'ostruct'
22
+ require 'optparse'
23
+
24
+ module RubyProf
25
+ class Cmd
26
+ attr_accessor :options
27
+
28
+ def initialize
29
+ setup_options
30
+ parse_args
31
+
32
+ load_pre_libs
33
+ load_pre_execs
34
+ end
35
+
36
+ def setup_options
37
+ @options = OpenStruct.new
38
+ options.printer = RubyProf::FlatPrinter
39
+ options.min_percent = 0
40
+ options.file = nil
41
+ options.replace_prog_name = false
42
+ options.specialized_instruction = false
43
+
44
+ options.pre_libs = Array.new
45
+ options.pre_execs = Array.new
46
+ end
47
+
48
+ def option_parser
49
+ OptionParser.new do |opts|
50
+ opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
51
+ "Usage: ruby-prof [options] <script.rb> [--] [profiled-script-command-line-options]"
52
+
53
+ opts.separator ""
54
+ opts.separator "Options:"
55
+
56
+ opts.on('-p printer', '--printer=printer', [:flat, :flat_with_line_numbers, :graph, :graph_html, :call_tree, :call_stack, :dot, :multi],
57
+ 'Select a printer:',
58
+ ' flat - Prints a flat profile as text (default).',
59
+ ' flat_with_line_numbers - same as flat, with line numbers.',
60
+ ' graph - Prints a graph profile as text.',
61
+ ' graph_html - Prints a graph profile as html.',
62
+ ' call_tree - format for KCacheGrind',
63
+ ' call_stack - prints a HTML visualization of the call tree',
64
+ ' dot - Prints a graph profile as a dot file',
65
+ ' multi - Creates several reports in output directory'
66
+ ) do |printer|
67
+
68
+
69
+ case printer
70
+ when :flat
71
+ options.printer = RubyProf::FlatPrinter
72
+ when :flat_with_line_numbers
73
+ options.printer = RubyProf::FlatPrinterWithLineNumbers
74
+ when :graph
75
+ options.printer = RubyProf::GraphPrinter
76
+ when :graph_html
77
+ options.printer = RubyProf::GraphHtmlPrinter
78
+ when :call_tree
79
+ options.printer = RubyProf::CallTreePrinter
80
+ when :call_stack
81
+ options.printer = RubyProf::CallStackPrinter
82
+ when :dot
83
+ options.printer = RubyProf::DotPrinter
84
+ when :multi
85
+ options.printer = RubyProf::MultiPrinter
86
+ end
87
+ end
88
+
89
+ opts.on('-m min_percent', '--min_percent=min_percent', Float,
90
+ 'The minimum percent a method must take before ',
91
+ ' being included in output reports.',
92
+ ' this option is not supported for call tree.') do |min_percent|
93
+ options.min_percent = min_percent
94
+ end
95
+
96
+ opts.on('-f path', '--file=path',
97
+ 'Output results to a file instead of standard out.') do |file|
98
+ options.file = file
99
+ options.old_wd = Dir.pwd
100
+ end
101
+
102
+ opts.on('--mode=measure_mode',
103
+ [:process, :wall, :cpu, :allocations, :memory, :gc_runs, :gc_time],
104
+ 'Select what ruby-prof should measure:',
105
+ ' wall - Wall time (default).',
106
+ ' process - Process time.',
107
+ ' cpu - CPU time (Pentium and PowerPCs only).',
108
+ ' 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|
112
+
113
+ case measure_mode
114
+ when :wall
115
+ options.measure_mode = RubyProf::WALL_TIME
116
+ when :process
117
+ options.measure_mode = RubyProf::PROCESS_TIME
118
+ when :cpu
119
+ options.measure_mode = RubyProf::CPU_TIME
120
+ when :allocations
121
+ options.measure_mode = RubyProf::ALLOCATIONS
122
+ when :memory
123
+ 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
+ end
129
+ end
130
+
131
+ opts.on('-s sort_mode', '--sort=sort_mode', [:total, :self, :wait, :child],
132
+ 'Select how ruby-prof results should be sorted:',
133
+ ' total - Total time',
134
+ ' self - Self time',
135
+ ' wait - Wait time',
136
+ ' child - Child time') do |sort_mode|
137
+
138
+ options.sort_method = case sort_mode
139
+ when :total
140
+ :total_time
141
+ when :self
142
+ :self_time
143
+ when :wait
144
+ :wait_time
145
+ when :child
146
+ :children_time
147
+ end
148
+ end
149
+
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
+ opts.on_tail("-h", "--help", "Show help message") do
161
+ puts opts
162
+ exit
163
+ end
164
+
165
+ opts.on_tail("--version", "Show version #{RubyProf::VERSION}") do
166
+ puts "ruby_prof " + RubyProf::VERSION
167
+ exit
168
+ end
169
+
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
177
+ end
178
+
179
+ opts.on('-R lib', '--require-noprof lib', 'require a specific library (not profiled)') do |lib|
180
+ options.pre_libs << lib
181
+ end
182
+
183
+ opts.on('-E code', '--eval-noprof code', 'execute the ruby statements (not profiled)') do |code|
184
+ options.pre_execs << code
185
+ end
186
+
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.
229
+ end
230
+
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
+ }
238
+ end
239
+ end
240
+ end
241
+
242
+ def parse_args
243
+ # Make sure the user specified at least one file
244
+ if ARGV.length < 1 and not options.exec
245
+ puts self.option_parser
246
+ puts ""
247
+ puts "Must specify a script to run"
248
+ exit(-1)
249
+ end
250
+
251
+ self.option_parser.parse! ARGV
252
+
253
+ if options.printer.needs_dir?
254
+ options.file ||= "."
255
+ options.old_wd ||= Dir.pwd
256
+ if !File.directory?(options.file)
257
+ puts "'#{options.file}' is not a directory"
258
+ puts "#{options.printer} needs an existing directory path to put profiles under."
259
+ exit(-1)
260
+ end
261
+ end
262
+ rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e
263
+ puts self.option_parser
264
+ puts e.message
265
+ exit(-1)
266
+ end
267
+
268
+ def load_pre_libs
269
+ options.pre_libs.each do |lib|
270
+ require lib
271
+ end
272
+ end
273
+
274
+ def load_pre_execs
275
+ options.pre_execs.each do |exec|
276
+ eval(exec)
277
+ end
278
+ end
279
+
280
+ def run
281
+ # Get the script we will execute
282
+ script = ARGV.shift
283
+ if options.replace_prog_name
284
+ $0 = File.expand_path(script)
285
+ end
286
+
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
+ }
293
+ end
294
+
295
+ # Set the measure mode
296
+ RubyProf.measure_mode = options.measure_mode if options.measure_mode
297
+ RubyProf.start_script(script)
298
+ end
299
+ end
300
+ end
301
+
302
+ # Parse command line options
303
+ cmd = RubyProf::Cmd.new
304
+
305
+ # Install at_exit handler. It is important that we do this
306
+ # before loading the scripts so our at_exit handler run
307
+ # *after* any other one that will be installed.
308
+
309
+ 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
+ # Create a printer
323
+ printer = cmd.options.printer.new(result)
324
+ printer_options = {:min_percent => cmd.options.min_percent, :sort_method => cmd.options.sort_method}
325
+
326
+ # Get output
327
+ if cmd.options.file
328
+ # 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.
329
+ Dir.chdir(cmd.options.old_wd) do
330
+ if printer.class.needs_dir?
331
+ printer.print(printer_options.merge(:path => cmd.options.file))
332
+ else
333
+ File.open(cmd.options.file, 'w') do |file|
334
+ printer.print(file, printer_options)
335
+ end
336
+ end
337
+ end
338
+ else
339
+ # Print out results
340
+ printer.print(STDOUT, printer_options)
341
+ end
342
+ }
343
+
344
+ # Now profile some code
345
+ cmd.run