forked from ruby-prof/ruby-prof
/
ruby-prof
224 lines (193 loc) · 7.61 KB
/
ruby-prof
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
#! /usr/bin/env ruby
# == Synopsis
#
# Profiles a Ruby program.
#
# == Usage
#
# ruby_prof [options] <script.rb> [--] [script-options]"
#
# Options:
# -p, --printer=printer Select a printer:
# flat - Prints a flat profile as text (default).
# flat_with_line_numbers - Above, with line numbers
# graph - Prints a graph profile as text.
# graph_html - Prints a graph profile as html.
# call_tree - format for KCacheGrind
# -f, --file=path Output results to a file instead of standard out.
# -m, --min_percent=min_percent The minimum percent a method must take before ',
# being included in output reports. Should be an
# integer between 1 and 100. 0 means all methods are printed.
# --mode=measure_mode Select a measurement mode:
# process - Use process time (default).
# wall - Use wall time.
# cpu - Use the CPU clock counter
# (only supported on Pentium and PowerPCs).
# allocations - Tracks object allocations
# (requires a patched Ruby interpreter).
# memory - Tracks total memory size
# (requires a patched Ruby interpreter).
# gc_runs - Tracks number of garbage collection runs
# (requires a patched Ruby interpreter).
# gc_time - Tracks time spent doing garbage collection
# (requires a patched Ruby interpreter).
# --replace-progname Replace $0 when loading the .rb files.
# --specialized-instruction Turn on specialized instruction.
# -h, --help Show help message
# --version Show version
# -v Show version, set $VERBOSE to true, run file
# -d Set $DEBUG to true
#
#
# See also: {flat profiles}[link:files/examples/flat_txt.html], {graph profiles}[link:files/examples/graph_txt.html], {html graph profiles}[link:files/examples/graph_html.html]
#
require 'ostruct'
require 'optparse'
require 'ruby-prof'
options = OpenStruct.new
options.measure_mode = RubyProf::PROCESS_TIME
options.printer = RubyProf::FlatPrinter
options.min_percent = 0
options.file = nil
options.replace_prog_name = false
options.specialized_instruction = false
opts = OptionParser.new do |opts|
opts.banner = "ruby_prof #{RubyProf::VERSION}\n" +
"Usage: ruby_prof [options] <script.rb> [--] [script-options]"
opts.separator ""
opts.separator "Options:"
opts.on('-p printer', '--printer=printer', [:flat, :flat_with_line_numbers, :graph, :graph_html, :call_tree],
'Select a printer:',
' flat - Prints a flat profile as text (default).',
' flat_with_line_numbers - same as flat, with line numbers.',
' graph - Prints a graph profile as text.',
' graph_html - Prints a graph profile as html.',
' call_tree - format for KCacheGrind'
) do |printer|
case printer
when :flat
options.printer = RubyProf::FlatPrinter
when :flat_with_line_numbers
options.printer = RubyProf::FlatPrinterWithLineNumbers
when :graph
options.printer = RubyProf::GraphPrinter
when :graph_html
options.printer = RubyProf::GraphHtmlPrinter
when :call_tree
options.printer = RubyProf::CallTreePrinter
end
end
opts.on('-m min_percent', '--min_percent=min_percent', Float,
'The minimum percent a method must take before ',
' being included in output reports.',
' this option is not supported for call tree.') do |min_percent|
options.min_percent = min_percent
end
opts.on('-f path', '--file=path',
'Output results to a file instead of standard out.') do |file|
options.file = file
end
opts.on('--mode=measure_mode',
[:process, :wall, :cpu, :allocations, :memory, :gc_runs, :gc_time],
'Select what ruby-prof should measure:',
' process - Process time (default).',
' wall - Wall time.',
' cpu - CPU time (Pentium and PowerPCs only).',
' allocations - Object allocations (requires patched Ruby interpreter).',
' memory - Allocated memory in KB (requires patched Ruby interpreter).',
' gc_runs - Number of garbage collections (requires patched Ruby interpreter).',
' gc_time - Time spent in garbage collection (requires patched Ruby interpreter).') do |measure_mode|
case measure_mode
when :process
options.measure_mode = RubyProf::PROCESS_TIME
when :wall
options.measure_mode = RubyProf::WALL_TIME
when :cpu
options.measure_mode = RubyProf::CPU_TIME
when :allocations
options.measure_mode = RubyProf::ALLOCATIONS
when :memory
options.measure_mode = RubyProf::MEMORY
when :gc_runs
options.measure_mode = RubyProf::GC_RUNS
when :gc_time
options.measure_mode = RubyProf::GC_TIME
end
end
opts.on("--replace-progname", "Replace $0 when loading the .rb files.") do
options.replace_prog_name = true
end
if defined?(VM)
opts.on("--specialized-instruction", "Turn on specified instruction.") do
options.specialized_instruction = true
end
end
opts.on_tail("-h", "--help", "Show help message") do
puts opts
exit
end
opts.on_tail("--version", "Show version #{RubyProf::VERSION}") do
puts "ruby_prof " + RubyProf::VERSION
exit
end
opts.on("-v","Show version, set $VERBOSE to true, profile script") do
puts "ruby_prof " + RubyProf::VERSION
puts "ruby " + RUBY_DESCRIPTION
$VERBOSE= true
end
opts.on("-d", "Set $DEBUG to true") do
$DEBUG = true
end
end
begin
opts.parse! ARGV
rescue OptionParser::InvalidOption, OptionParser::InvalidArgument,
OptionParser::MissingArgument => e
puts opts
puts
puts e.message
exit(-1)
end
# Make sure the user specified at least one file
if ARGV.length < 1
puts opts
puts ""
puts "Must specify a script to run"
exit(-1)
end
# Install at_exit handler. It is important that we do this
# before loading the scripts so our at_exit handler run
# *after* any other one that will be installed.
at_exit {
# Stop profiling
result = RubyProf.stop
# Create a printer
printer = options.printer.new(result)
# Get output
if options.file
File.open(options.file, 'w') do |file|
printer.print(file, {:min_percent => options.min_percent})
end
else
# Print out results
printer.print(STDOUT, {:min_percent => options.min_percent})
end
}
# Now set measure mode
RubyProf.measure_mode = options.measure_mode
# Set VM compile option
if defined?(VM)
VM::InstructionSequence.compile_option = {
:trace_instruction => true,
:specialized_instruction => options.specialized_instruction
}
end
# Get the script we will execute
script = ARGV.shift
if options.replace_prog_name
$0 = File.expand_path(script)
end
# Start profiling
RubyProf.start
# Load the script
load script