3 # Must use our benchmark.rb, which has bug fixes -vs- Ruby 1.8.6 pl 111
4 require File
.expand_path(File
.join(File
.dirname(__FILE__
),'../lib/benchmark'))
11 # Benchmark test selector
12 # BM_GLOB = 'test/benchmark/*/bm*.rb'
13 BM_GLOB
= File
.expand_path(File
.join(File
.dirname(__FILE__
),'../benchmark/*/bm*.rb'))
15 # Which Ruby runtimes to test: MRI should be first and Rubinius should be last
16 $interpreters = ['ruby','shotgun/rubinius']
18 # WIDTH of test labels, required for nice formating
21 REPORT_WIDTH
= WIDTH
- 6
24 DECIMAL_FORMAT
= '%4.4f'
27 NOW
= "#{now.year}-#{'%02d' % now.month}-#{'%02d' % now.day}-" +
28 "#{'%02d' % now.hour}-#{'%02d' % now.min}-#{'%02d' % now.sec}"
30 OPTIONS
= OpenStruct
.new( :size => 1024,
33 options
= OptionParser
.new
do |opts
|
34 opts
.on('-c', '--chart [FILENAME]', 'Output passing test times to SVG file at --path') do |c
|
35 OPTIONS
.chart
= c
|| "#{NOW}-times.svg"
38 opts
.on('-d', '--diff-chart [FILENAME]', 'Output speed differences to SVG file at --path') do |d
|
39 OPTIONS
.diffchart
= d
|| "#{NOW}-difference.svg"
42 opts
.on('-f', '--file [FILENAME]', 'Output report to text file at --path, instead of STDOUT') do |f
|
43 OPTIONS
.file
= f
|| "#{NOW}-report.txt"
46 opts
.on('-g', '--grep REGEX', 'Only run tests that match REGEX') do |g
|
50 opts
.on("-t", "--target TARGET", String
,
51 "Use TARGET to compare against: r:ruby|r19:ruby19|x:rbx|j:jruby") do |t
|
57 when 'x', 'rbx', 'rubinius'
58 target
= 'shotgun/rubinius'
64 $interpreters.insert(1,target
)
67 opts
.on('-j', '--just', 'Benchmark just the target machine') do |j
|
68 $interpreters.delete_at(0)
71 opts
.on('-h', '--help', 'Output this help information') do |h
|
75 opts
.on('-n', '--ngrep REGEX', 'Only run tests that do not match REGEX') do |n
|
79 opts
.on('-p', '--path PATH', 'Path prefix for --chart, --diff-chart, and --file') do |p
|
83 opts
.on('-s', '--size PIXELS', 'Size, in pixels, of --chart and/or --diff-chart') do |s
|
87 opts
.on('-w', '--warmup', 'Run each test twice and throw away the first result') do |w
|
95 puts options
.summarize
99 class RbxBenchmarkFile
100 def initialize(interpreter
,file
)
101 @interpreter = interpreter
105 def pretty_interpreter
106 @interpreter.match(%r
{ruby19
|rubinius
|ruby
|jruby
})[0]
110 @file.match(%r
{[^
/]+/[^
/]+$
})[0]
114 pretty_interpreter
+ ': ' + pretty_file
118 command
= "#{@interpreter} #{@file}"
121 when /borasky\/bm_MatrixBenchmark
[.]rb
/
129 command
+ ' > /dev/null 2>&1'
133 spaces
= WIDTH
- label
.length
134 spaces
= spaces
< 0 ? 0 : spaces
136 @result = if OPTIONS
.warmup
then
137 Benchmark
.bmbm
do |x
|
138 x
.report(label
+ ' ' * spaces
) do
139 if system quiet_command
then
149 x
.report(label
+ ' ' * spaces
) do
150 if system quiet_command
then
170 passed
? ? @result.real
: 0
189 DECIMAL_FORMAT
% time
192 end.rjust(COLUMN_WIDTH
)
196 class RbxBenchmarkRun
197 attr_reader
:interpreter
200 def initialize(interpreter
)
201 @interpreter = interpreter
203 @total = Benchmark
::Tms.new
207 if @interpreter =~
/rubinius/ then
208 Dir
[BM_GLOB
+ 'c'].each
do |file
|
217 Dir
[BM_GLOB
].each
do |file
|
218 @results << RbxBenchmarkFile
.new(@interpreter,file
)
220 if OPTIONS
.grep
and ! file
.match(OPTIONS
.grep
)
225 if OPTIONS
.ngrep
and file
.match(OPTIONS
.ngrep
) then
237 @results.inject(0) { |total
, result
| total
+ result
.time
}
241 @results.collect
do |result
|
242 if result
.unchartable
?
251 def difference(ruby
,rubinius
)
252 if ruby
.unchartable
? or rubinius
.unchartable
? then
254 elsif ruby
.time
< rubinius
.time
then
255 -rubinius
.time
/ ruby
.time
257 ruby
.time
/ rubinius
.time
262 header
= 'file'.ljust(REPORT_WIDTH
)
265 header
<< (run
.results
.first
.pretty_interpreter
).rjust(COLUMN_WIDTH
)
268 header
<< 'difference'.rjust(COLUMN_WIDTH
)
273 file
= File
.open(OPTIONS
.path
+ OPTIONS
.file
,'w')
279 file
.puts
'-' * header
.length
281 # Columnar result output
282 0.upto(runs
.first
.results
.length
- 1) do |i
|
283 line
= runs
.first
.results
[i
].pretty_file
.ljust(REPORT_WIDTH
)
286 results
<< run
.results
[i
]
287 line
<< run
.results
[i
].report
290 diff
= difference(results
.first
,results
.last
)
292 line
<< if diff
.nil? then
295 DECIMAL_FORMAT
% diff
296 end.rjust(COLUMN_WIDTH
)
301 file
.close
unless file
== STDOUT
306 $interpreters.each
do |i
|
307 runs
<< RbxBenchmarkRun
.new(i
).run
312 if OPTIONS
.chart
or OPTIONS
.diffchart
then
317 if OPTIONS
.chart
then
318 chart_point_sets
= runs
.collect
{ |run
| run
.chart_points
}
320 # Make a list of failed tests
323 for i
in 0..chart_point_sets
.length-1
325 for j
in 0..chart_point_sets
.first
.length-1
326 if chart_point_sets
[i
][j
].nil? then
332 # Remove failed tests from each runtime
333 chart_point_sets
.each
do |cps
|
334 deletes
.uniq
.sort
.reverse
.each
{ |d
| cps
.delete_at(d
) }
337 graph
= Scruffy
::Graph.new
340 graph
<< Scruffy
::Layers::Line.new( :title => run
.interpreter
,
341 :points => chart_point_sets
.shift
)
344 # graph.point_markers = runs.first.results.reject do |result|
345 # result.unchartable?
346 # end.collect do |result|
350 puts
"Rendering chart to #{OPTIONS.chart}"
352 graph
.render( :width => OPTIONS
.size
, :to => OPTIONS
.path
+ OPTIONS
.chart
)
355 if OPTIONS
.diffchart
then
359 0.upto(runs
.first
.results
.length
- 1) do |i
|
360 differences
<< difference(runs
.first
.results
[i
],runs
.last
.results
[i
])
363 # Remove where tests failed, easier this time, only a single list
364 differences
.reject
! { |d
| d
.nil? }
366 # Convert to percentages
367 # differences.collect { |d| d * 100 }
369 graph
= Scruffy
::Graph.new
371 graph
<< Scruffy
::Layers::Line.new( :title => 'Zero',
372 :points => differences
.collect
{ |d
| 0 } )
374 graph
<< Scruffy
::Layers::Line.new( :title => 'Rubinius times faster (-times slower)',
375 :points => differences
)
377 # graph.point_markers = runs.first.results.reject do |result|
378 # result.unchartable?
379 # end.collect do |result|
383 puts
"Rendering diffchart to #{OPTIONS.diffchart}"
385 graph
.render( :width => OPTIONS
.size
, :to => OPTIONS
.path
+ OPTIONS
.diffchart
)