airbnb-ruby-prof 0.0.1
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.
- data/CHANGES +483 -0
- data/LICENSE +25 -0
- data/README.rdoc +426 -0
- data/Rakefile +51 -0
- data/bin/ruby-prof +279 -0
- data/bin/ruby-prof-check-trace +45 -0
- data/examples/flat.txt +50 -0
- data/examples/graph.dot +84 -0
- data/examples/graph.html +823 -0
- data/examples/graph.txt +139 -0
- data/examples/multi.flat.txt +23 -0
- data/examples/multi.graph.html +760 -0
- data/examples/multi.grind.dat +114 -0
- data/examples/multi.stack.html +547 -0
- data/examples/stack.html +547 -0
- data/ext/ruby_prof/extconf.rb +67 -0
- data/ext/ruby_prof/rp_call_info.c +374 -0
- data/ext/ruby_prof/rp_call_info.h +59 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.c +247 -0
- data/ext/ruby_prof/rp_fast_call_tree_printer.h +10 -0
- data/ext/ruby_prof/rp_measure.c +71 -0
- data/ext/ruby_prof/rp_measure.h +56 -0
- data/ext/ruby_prof/rp_measure_allocations.c +74 -0
- data/ext/ruby_prof/rp_measure_cpu_time.c +134 -0
- data/ext/ruby_prof/rp_measure_gc_runs.c +71 -0
- data/ext/ruby_prof/rp_measure_gc_time.c +58 -0
- data/ext/ruby_prof/rp_measure_memory.c +75 -0
- data/ext/ruby_prof/rp_measure_process_time.c +69 -0
- data/ext/ruby_prof/rp_measure_wall_time.c +43 -0
- data/ext/ruby_prof/rp_method.c +717 -0
- data/ext/ruby_prof/rp_method.h +79 -0
- data/ext/ruby_prof/rp_stack.c +221 -0
- data/ext/ruby_prof/rp_stack.h +81 -0
- data/ext/ruby_prof/rp_thread.c +312 -0
- data/ext/ruby_prof/rp_thread.h +36 -0
- data/ext/ruby_prof/ruby_prof.c +800 -0
- data/ext/ruby_prof/ruby_prof.h +64 -0
- data/ext/ruby_prof/vc/ruby_prof.sln +32 -0
- data/ext/ruby_prof/vc/ruby_prof_18.vcxproj +108 -0
- data/ext/ruby_prof/vc/ruby_prof_19.vcxproj +110 -0
- data/ext/ruby_prof/vc/ruby_prof_20.vcxproj +110 -0
- data/lib/ruby-prof.rb +63 -0
- data/lib/ruby-prof/aggregate_call_info.rb +76 -0
- data/lib/ruby-prof/assets/call_stack_printer.css.html +117 -0
- data/lib/ruby-prof/assets/call_stack_printer.js.html +385 -0
- data/lib/ruby-prof/assets/call_stack_printer.png +0 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.css.html +149 -0
- data/lib/ruby-prof/assets/flame_graph_printer.lib.js.html +707 -0
- data/lib/ruby-prof/assets/flame_graph_printer.page.js.html +56 -0
- data/lib/ruby-prof/assets/flame_graph_printer.tmpl.html.erb +39 -0
- data/lib/ruby-prof/call_info.rb +111 -0
- data/lib/ruby-prof/call_info_visitor.rb +40 -0
- data/lib/ruby-prof/compatibility.rb +186 -0
- data/lib/ruby-prof/method_info.rb +109 -0
- data/lib/ruby-prof/printers/abstract_printer.rb +85 -0
- data/lib/ruby-prof/printers/call_info_printer.rb +41 -0
- data/lib/ruby-prof/printers/call_stack_printer.rb +260 -0
- data/lib/ruby-prof/printers/call_tree_printer.rb +130 -0
- data/lib/ruby-prof/printers/dot_printer.rb +132 -0
- data/lib/ruby-prof/printers/fast_call_tree_printer.rb +87 -0
- data/lib/ruby-prof/printers/flame_graph_html_printer.rb +59 -0
- data/lib/ruby-prof/printers/flame_graph_json_printer.rb +157 -0
- data/lib/ruby-prof/printers/flat_printer.rb +70 -0
- data/lib/ruby-prof/printers/flat_printer_with_line_numbers.rb +64 -0
- data/lib/ruby-prof/printers/graph_html_printer.rb +244 -0
- data/lib/ruby-prof/printers/graph_printer.rb +116 -0
- data/lib/ruby-prof/printers/multi_printer.rb +58 -0
- data/lib/ruby-prof/profile.rb +22 -0
- data/lib/ruby-prof/profile/exclude_common_methods.rb +201 -0
- data/lib/ruby-prof/rack.rb +95 -0
- data/lib/ruby-prof/task.rb +147 -0
- data/lib/ruby-prof/thread.rb +35 -0
- data/lib/ruby-prof/version.rb +4 -0
- data/lib/ruby-prof/walker.rb +95 -0
- data/lib/unprof.rb +10 -0
- data/ruby-prof.gemspec +56 -0
- data/test/aggregate_test.rb +136 -0
- data/test/basic_test.rb +128 -0
- data/test/block_test.rb +74 -0
- data/test/call_info_test.rb +78 -0
- data/test/call_info_visitor_test.rb +31 -0
- data/test/duplicate_names_test.rb +32 -0
- data/test/dynamic_method_test.rb +55 -0
- data/test/enumerable_test.rb +21 -0
- data/test/exceptions_test.rb +16 -0
- data/test/exclude_methods_test.rb +146 -0
- data/test/exclude_threads_test.rb +53 -0
- data/test/fiber_test.rb +79 -0
- data/test/issue137_test.rb +63 -0
- data/test/line_number_test.rb +71 -0
- data/test/measure_allocations_test.rb +26 -0
- data/test/measure_cpu_time_test.rb +213 -0
- data/test/measure_gc_runs_test.rb +32 -0
- data/test/measure_gc_time_test.rb +36 -0
- data/test/measure_memory_test.rb +33 -0
- data/test/measure_process_time_test.rb +63 -0
- data/test/measure_wall_time_test.rb +255 -0
- data/test/module_test.rb +45 -0
- data/test/multi_measure_test.rb +38 -0
- data/test/multi_printer_test.rb +83 -0
- data/test/no_method_class_test.rb +15 -0
- data/test/pause_resume_test.rb +166 -0
- data/test/prime.rb +54 -0
- data/test/printers_test.rb +255 -0
- data/test/printing_recursive_graph_test.rb +127 -0
- data/test/rack_test.rb +93 -0
- data/test/recursive_test.rb +212 -0
- data/test/singleton_test.rb +38 -0
- data/test/stack_printer_test.rb +65 -0
- data/test/stack_test.rb +138 -0
- data/test/start_stop_test.rb +112 -0
- data/test/test_helper.rb +264 -0
- data/test/thread_test.rb +187 -0
- data/test/unique_call_path_test.rb +202 -0
- data/test/yarv_test.rb +55 -0
- metadata +211 -0
data/Rakefile
ADDED
@@ -0,0 +1,51 @@
|
|
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
|
+
rescue LoadError
|
13
|
+
$stderr.puts "Install bundler to get support for simplified gem publishing"
|
14
|
+
end
|
15
|
+
|
16
|
+
GEM_NAME = 'ruby-prof'
|
17
|
+
SO_NAME = 'ruby_prof'
|
18
|
+
|
19
|
+
default_spec = Gem::Specification.load("#{GEM_NAME}.gemspec")
|
20
|
+
|
21
|
+
# specify which versions/builds to cross compile
|
22
|
+
Rake::ExtensionTask.new do |ext|
|
23
|
+
ext.gem_spec = default_spec
|
24
|
+
ext.name = SO_NAME
|
25
|
+
ext.ext_dir = "ext/#{SO_NAME}"
|
26
|
+
ext.lib_dir = "lib/#{RUBY_VERSION}"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Rake task to build the default package
|
30
|
+
Gem::PackageTask.new(default_spec) do |pkg|
|
31
|
+
pkg.need_tar = true
|
32
|
+
end
|
33
|
+
|
34
|
+
task :default => :test
|
35
|
+
|
36
|
+
for file in Dir['lib/**/*.{o,so,bundle}']
|
37
|
+
CLEAN.include file
|
38
|
+
end
|
39
|
+
CLEAN.reject!{|f| !File.exist?(f)}
|
40
|
+
task :clean do
|
41
|
+
# remove tmp dir contents completely after cleaning
|
42
|
+
FileUtils.rm_rf('tmp/*')
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'Run the ruby-prof test suite'
|
46
|
+
Rake::TestTask.new do |t|
|
47
|
+
t.libs += %w(lib ext test)
|
48
|
+
t.test_files = Dir['test/**_test.rb']
|
49
|
+
t.verbose = true
|
50
|
+
t.warning = true
|
51
|
+
end
|
data/bin/ruby-prof
ADDED
@@ -0,0 +1,279 @@
|
|
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
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
def parse_args
|
191
|
+
# Make sure the user specified at least one file
|
192
|
+
if ARGV.length < 1 and not options.exec
|
193
|
+
puts self.option_parser
|
194
|
+
puts ""
|
195
|
+
puts "Must specify a script to run"
|
196
|
+
exit(-1)
|
197
|
+
end
|
198
|
+
|
199
|
+
self.option_parser.parse! ARGV
|
200
|
+
|
201
|
+
if options.printer == RubyProf::MultiPrinter
|
202
|
+
options.file ||= "."
|
203
|
+
options.old_wd ||= Dir.pwd
|
204
|
+
end
|
205
|
+
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument, OptionParser::MissingArgument => e
|
206
|
+
puts self.option_parser
|
207
|
+
puts e.message
|
208
|
+
exit(-1)
|
209
|
+
end
|
210
|
+
|
211
|
+
def load_pre_libs
|
212
|
+
options.pre_libs.each do |lib|
|
213
|
+
require lib
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def load_pre_execs
|
218
|
+
options.pre_execs.each do |exec|
|
219
|
+
eval(exec)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def run
|
224
|
+
# Get the script we will execute
|
225
|
+
script = ARGV.shift
|
226
|
+
if options.replace_prog_name
|
227
|
+
$0 = File.expand_path(script)
|
228
|
+
end
|
229
|
+
|
230
|
+
# Set VM compile option
|
231
|
+
if defined?(RubyVM)
|
232
|
+
RubyVM::InstructionSequence.compile_option = {
|
233
|
+
:trace_instruction => true,
|
234
|
+
:specialized_instruction => options.specialized_instruction
|
235
|
+
}
|
236
|
+
end
|
237
|
+
|
238
|
+
# Set the measure mode
|
239
|
+
RubyProf.measure_mode = options.measure_mode if options.measure_mode
|
240
|
+
RubyProf.start_script(script)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Parse command line options
|
246
|
+
cmd = RubyProf::Cmd.new
|
247
|
+
|
248
|
+
# Install at_exit handler. It is important that we do this
|
249
|
+
# before loading the scripts so our at_exit handler run
|
250
|
+
# *after* any other one that will be installed.
|
251
|
+
|
252
|
+
at_exit {
|
253
|
+
# Stop profiling
|
254
|
+
result = RubyProf.stop
|
255
|
+
|
256
|
+
# Create a printer
|
257
|
+
printer = cmd.options.printer.new(result)
|
258
|
+
printer_options = {:min_percent => cmd.options.min_percent, :sort_method => cmd.options.sort_method}
|
259
|
+
|
260
|
+
# Get output
|
261
|
+
if cmd.options.file
|
262
|
+
# 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.
|
263
|
+
Dir.chdir(cmd.options.old_wd) do
|
264
|
+
if printer.is_a?(RubyProf::MultiPrinter)
|
265
|
+
printer.print(printer_options.merge(:path => cmd.options.file))
|
266
|
+
else
|
267
|
+
File.open(cmd.options.file, 'w') do |file|
|
268
|
+
printer.print(file, printer_options)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
else
|
273
|
+
# Print out results
|
274
|
+
printer.print(STDOUT, printer_options)
|
275
|
+
end
|
276
|
+
}
|
277
|
+
|
278
|
+
# Now profile some code
|
279
|
+
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
|
data/examples/flat.txt
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
= Flat Profiles
|
2
|
+
|
3
|
+
Flat profiles show the total amount of time spent in each method.
|
4
|
+
As an example, here is the output from running printers_test.rb.
|
5
|
+
|
6
|
+
Measure Mode: wall_time
|
7
|
+
Thread ID: 70355159212340
|
8
|
+
Fiber ID: 70355171633140
|
9
|
+
Total: 0.060485
|
10
|
+
Sort by: self_time
|
11
|
+
|
12
|
+
%self total self wait child calls name
|
13
|
+
97.07 0.059 0.059 0.000 0.000 1001 Integer#upto
|
14
|
+
0.92 0.059 0.001 0.000 0.059 1000 Object#is_prime
|
15
|
+
0.66 0.060 0.000 0.000 0.059 1 Array#select
|
16
|
+
0.59 0.000 0.000 0.000 0.000 1000 Kernel#rand
|
17
|
+
0.50 0.001 0.000 0.000 0.000 1 Array#each_index
|
18
|
+
0.20 0.000 0.000 0.000 0.000 1000 Kernel#respond_to_missing?
|
19
|
+
0.01 0.000 0.000 0.000 0.000 1 Object#find_largest
|
20
|
+
0.01 0.060 0.000 0.000 0.060 1 PrintersTest#setup
|
21
|
+
0.01 0.060 0.000 0.000 0.060 1 Object#find_primes
|
22
|
+
0.01 0.000 0.000 0.000 0.000 1 Class#new
|
23
|
+
0.01 0.060 0.000 0.000 0.060 1 Object#run_primes
|
24
|
+
0.00 0.000 0.000 0.000 0.000 1 Array#first
|
25
|
+
0.00 0.001 0.000 0.000 0.001 1 Object#make_random_array
|
26
|
+
0.00 0.000 0.000 0.000 0.000 1 Array#initialize
|
27
|
+
|
28
|
+
All values are in seconds.
|
29
|
+
|
30
|
+
The columns are:
|
31
|
+
|
32
|
+
%self - The percentage of time spent in this method, derived from self_time/total_time
|
33
|
+
total - The time spent in this method and its children.
|
34
|
+
self - The time spent in this method.
|
35
|
+
wait - amount of time this method waited for other threads
|
36
|
+
child - The time spent in this method's children.
|
37
|
+
calls - The number of times this method was called.
|
38
|
+
name - The name of the method.
|
39
|
+
|
40
|
+
Methods are sorted based on %self, therefore the methods that execute the longest are listed
|
41
|
+
first.
|
42
|
+
|
43
|
+
For example, wee can see that Integer#upto took the most time, 0.059
|
44
|
+
seconds. Method Object#is_prime calls this method, so the 0.59
|
45
|
+
seconds appear as child time for Object#is_prime.
|
46
|
+
|
47
|
+
The interpretation of method names is:
|
48
|
+
* MyObject#test - An instance method "test" of the class "MyObject"
|
49
|
+
* <Object:MyObject>#test - The <> characters indicate a singleton method on a singleton class.
|
50
|
+
|
data/examples/graph.dot
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
digraph "Profile" {
|
2
|
+
labelloc=t;
|
3
|
+
labeljust=l;
|
4
|
+
subgraph "Thread 70140045951280" {
|
5
|
+
70140046535720 [label="setup\n(100%)"];
|
6
|
+
70140046535720 -> 70140046535660 [label="1/1" fontsize=10 fontcolor="#666666"];
|
7
|
+
70140046535660 [label="run_primes\n(100%)"];
|
8
|
+
70140046535660 -> 70140046534940 [label="1/1" fontsize=10 fontcolor="#666666"];
|
9
|
+
70140046535660 -> 70140046535640 [label="1/1" fontsize=10 fontcolor="#666666"];
|
10
|
+
70140046535660 -> 70140046534640 [label="1/1" fontsize=10 fontcolor="#666666"];
|
11
|
+
70140046534940 [label="find_primes\n(93%)"];
|
12
|
+
70140046534940 -> 70140046534920 [label="1/1" fontsize=10 fontcolor="#666666"];
|
13
|
+
70140046534920 [label="select\n(93%)"];
|
14
|
+
70140046534920 -> 70140046534840 [label="200/200" fontsize=10 fontcolor="#666666"];
|
15
|
+
70140046534840 [label="is_prime\n(90%)"];
|
16
|
+
70140046534840 -> 70140046534820 [label="200/201" fontsize=10 fontcolor="#666666"];
|
17
|
+
70140046534820 [label="upto\n(87%)"];
|
18
|
+
70140046535640 [label="make_random_array\n(7%)"];
|
19
|
+
70140046535640 -> 70140046535500 [label="1/1" fontsize=10 fontcolor="#666666"];
|
20
|
+
70140046535640 -> 70140046535600 [label="1/1" fontsize=10 fontcolor="#666666"];
|
21
|
+
70140046535500 [label="each_index\n(6%)"];
|
22
|
+
70140046535500 -> 70140046535140 [label="200/200" fontsize=10 fontcolor="#666666"];
|
23
|
+
70140046535140 [label="rand\n(4%)"];
|
24
|
+
70140046535140 -> 70140046535100 [label="200/200" fontsize=10 fontcolor="#666666"];
|
25
|
+
70140046535100 [label="respond_to_missing?\n(1%)"];
|
26
|
+
70140046534640 [label="find_largest\n(1%)"];
|
27
|
+
70140046534640 -> 70140046534820 [label="1/201" fontsize=10 fontcolor="#666666"];
|
28
|
+
70140046534640 -> 70140046534620 [label="1/1" fontsize=10 fontcolor="#666666"];
|
29
|
+
70140046535600 [label="new\n(0%)"];
|
30
|
+
70140046535600 -> 70140046535580 [label="1/1" fontsize=10 fontcolor="#666666"];
|
31
|
+
70140046535580 [label="initialize\n(0%)"];
|
32
|
+
70140046534620 [label="first\n(0%)"];
|
33
|
+
}
|
34
|
+
subgraph cluster_70140046962360 {
|
35
|
+
label = "PrintersTest";
|
36
|
+
fontcolor = "#666666";
|
37
|
+
fontsize = 16;
|
38
|
+
color = "#666666";
|
39
|
+
70140046535720;
|
40
|
+
}
|
41
|
+
subgraph cluster_70140046962240 {
|
42
|
+
label = "Object";
|
43
|
+
fontcolor = "#666666";
|
44
|
+
fontsize = 16;
|
45
|
+
color = "#666666";
|
46
|
+
70140046535660;
|
47
|
+
70140046535640;
|
48
|
+
70140046534940;
|
49
|
+
70140046534840;
|
50
|
+
70140046534640;
|
51
|
+
}
|
52
|
+
subgraph cluster_70140046962040 {
|
53
|
+
label = "Class";
|
54
|
+
fontcolor = "#666666";
|
55
|
+
fontsize = 16;
|
56
|
+
color = "#666666";
|
57
|
+
70140046535600;
|
58
|
+
}
|
59
|
+
subgraph cluster_70140046961920 {
|
60
|
+
label = "Array";
|
61
|
+
fontcolor = "#666666";
|
62
|
+
fontsize = 16;
|
63
|
+
color = "#666666";
|
64
|
+
70140046535580;
|
65
|
+
70140046535500;
|
66
|
+
70140046534920;
|
67
|
+
70140046534620;
|
68
|
+
}
|
69
|
+
subgraph cluster_70140046961720 {
|
70
|
+
label = "Kernel";
|
71
|
+
fontcolor = "#666666";
|
72
|
+
fontsize = 16;
|
73
|
+
color = "#666666";
|
74
|
+
70140046535140;
|
75
|
+
70140046535100;
|
76
|
+
}
|
77
|
+
subgraph cluster_70140046961280 {
|
78
|
+
label = "Integer";
|
79
|
+
fontcolor = "#666666";
|
80
|
+
fontsize = 16;
|
81
|
+
color = "#666666";
|
82
|
+
70140046534820;
|
83
|
+
}
|
84
|
+
}
|