2 # Ruby Benchmark driver
\r
9 class BenchmarkDriver
\r
10 def self.benchmark(opt)
\r
11 driver = self.new(opt[:execs], opt[:dir], opt)
\r
21 @output and @output.puts(*args)
\r
25 output(*args) if @verbose
\r
28 def message_print *args
\r
32 @output and @output.print(*args)
\r
36 def progress_message *args
\r
38 STDERR.print(*args)
\r
43 def initialize execs, dir, opt = {}
\r
44 @execs = execs.map{|e|
\r
48 if /(.+)::(.+)/ =~ e
\r
49 # ex) ruby-a::/path/to/ruby-a
\r
54 v.sub!(/ patchlevel \d+/, '')
\r
60 @repeat = opt[:repeat] || 1
\r
61 @repeat = 1 if @repeat < 1
\r
62 @pattern = opt[:pattern] || nil
\r
63 @verbose = opt[:quiet] ? false : (opt[:verbose] || false)
\r
64 @output = opt[:output] ? open(opt[:output], 'w') : nil
\r
65 @loop_wl1 = @loop_wl2 = nil
\r
68 # [[name, [[r-1-1, r-1-2, ...], [r-2-1, r-2-2, ...]]], ...]
\r
72 @start_time = Time.now
\r
74 @execs.each_with_index{|(e, v), i|
\r
75 message "target #{i}: #{v}"
\r
84 message '-----------------------------------------------------------'
\r
87 message PP.pp(@results, "", 79)
\r
89 message "Elapesed time: #{Time.now - @start_time} (sec)"
\r
92 output '-----------------------------------------------------------'
\r
93 output 'benchmark results:'
\r
95 if @verbose and @repeat > 1
\r
96 output "minimum results in each #{@repeat} measurements."
\r
99 output "name\t#{@execs.map{|(e, v)| v}.join("\t")}"
\r
100 @results.each{|v, result|
\r
103 result.each_with_index{|e, i|
\r
117 rets << sprintf("%.3f", r)
\r
119 output "#{v}#{s}\t#{rets.join("\t")}"
\r
125 vm1 = vm2 = wl1 = wl2 = false
\r
126 @files = Dir.glob(File.join(@dir, 'bm*.rb')).map{|file|
\r
127 next if @pattern && /#{@pattern}/ !~ File.basename(file)
\r
129 when /bm_(vm[12])_/, /bm_loop_(whileloop2?).rb/
\r
135 if flag['vm1'] && !flag['whileloop']
\r
136 @files << File.join(@dir, 'bm_loop_whileloop.rb')
\r
137 elsif flag['vm2'] && !flag['whileloop2']
\r
138 @files << File.join(@dir, 'bm_loop_whileloop2.rb')
\r
142 progress_message "total: #{@files.size * @repeat} trial(s) (#{@repeat} trial(s) for #{@files.size} benchmark(s))\n"
\r
147 files.each_with_index{|file, i|
\r
149 r = measure_file(file)
\r
151 if /bm_loop_whileloop.rb/ =~ file
\r
152 @loop_wl1 = r[1].map{|e| e.min}
\r
153 elsif /bm_loop_whileloop2.rb/ =~ file
\r
154 @loop_wl2 = r[1].map{|e| e.min}
\r
159 def measure_file file
\r
160 name = File.basename(file, '.rb').sub(/^bm_/, '')
\r
161 prepare_file = File.join(File.dirname(file), "prepare_#{name}.rb")
\r
162 load prepare_file if FileTest.exist?(prepare_file)
\r
166 output '-----------------------------------------------------------'
\r
169 output File.read(file)
\r
174 result << @execs.map{|(e, v)|
\r
176 message_print "#{v}\t"
\r
177 progress_message '.'
\r
179 m = measure(e, file)
\r
188 def measure executable, file
\r
189 cmd = "#{executable} #{file}"
\r
190 m = Benchmark.measure{
\r
195 raise "Benchmark process exited with abnormal status (#{$?})"
\r
204 :execs => ['ruby'],
\r
207 :output => "bmlog-#{Time.now.strftime('%Y%m%d-%H%M%S')}.#{$$}",
\r
210 parser = OptionParser.new{|o|
\r
211 o.on('-e', '--executables [EXECS]',
\r
212 "Specify benchmark one or more targets. (exec1; exec2; exec3, ...)"){|e|
\r
213 opt[:execs] = e.split(/;/)
\r
215 o.on('-d', '--directory [DIRECTORY]', "Benchmark suites directory"){|d|
\r
218 o.on('-p', '--pattern [PATTERN]', "Benchmark name pattern"){|p|
\r
221 o.on('-r', '--repeat-count [NUM]', "Repeat count"){|n|
\r
222 opt[:repeat] = n.to_i
\r
224 o.on('-o', '--output-file [FILE]', "Output file"){|o|
\r
227 o.on('-q', '--quiet', "Run without notify information except result table."){|q|
\r
230 o.on('-v', '--verbose'){|v|
\r
235 parser.parse!(ARGV)
\r
236 BenchmarkDriver.benchmark(opt)
\r