mirror of
				https://github.com/ruby/ruby.git
				synced 2022-11-09 12:17:21 -05:00 
			
		
		
		
	 58b1f91b46
			
		
	
	
		58b1f91b46
		
	
	
	
	
		
			
			in build directory. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13993 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
		
			
				
	
	
		
			253 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			253 lines
		
	
	
	
		
			5.4 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| #
 | |
| # Ruby Benchmark driver
 | |
| #
 | |
| 
 | |
| first = true
 | |
| 
 | |
| p RUBY_VERSION
 | |
| 
 | |
| begin
 | |
|   require 'optparse'
 | |
| rescue LoadError
 | |
|   if first
 | |
|     first = false
 | |
|     $:.unshift File.join(File.dirname(__FILE__), '../lib')
 | |
|     retry
 | |
|   else
 | |
|     raise
 | |
|   end
 | |
| end
 | |
| 
 | |
| require 'benchmark'
 | |
| require 'pp'
 | |
| 
 | |
| class BenchmarkDriver
 | |
|   def self.benchmark(opt)
 | |
|     driver = self.new(opt[:execs], opt[:dir], opt)
 | |
|     begin
 | |
|       driver.run
 | |
|     ensure
 | |
|       driver.show_results
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def output *args
 | |
|     puts(*args)
 | |
|     @output and @output.puts(*args)
 | |
|   end
 | |
| 
 | |
|   def message *args
 | |
|     output(*args) if @verbose
 | |
|   end
 | |
| 
 | |
|   def message_print *args
 | |
|     if @verbose
 | |
|       print(*args)
 | |
|       STDOUT.flush
 | |
|       @output and @output.print(*args)
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def progress_message *args
 | |
|     unless STDOUT.tty?
 | |
|       STDERR.print(*args) 
 | |
|       STDERR.flush
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def initialize execs, dir, opt = {}
 | |
|     @execs = execs.map{|e|
 | |
|       e.strip!
 | |
|       next if e.empty?
 | |
| 
 | |
|       if /(.+)::(.+)/ =~ e
 | |
|         # ex) ruby-a::/path/to/ruby-a
 | |
|         v = $1.strip
 | |
|         e = $2
 | |
|       else
 | |
|         v =  `#{e} -v`.chomp
 | |
|         v.sub!(/ patchlevel \d+/, '')
 | |
|       end
 | |
|       [e, v]
 | |
|     }.compact
 | |
| 
 | |
|     @dir = dir
 | |
|     @repeat = opt[:repeat] || 1
 | |
|     @repeat = 1 if @repeat < 1
 | |
|     @pattern = opt[:pattern] || nil
 | |
|     @verbose = opt[:quiet] ? false : (opt[:verbose] || false)
 | |
|     @output = opt[:output] ? open(opt[:output], 'w') : nil
 | |
|     @loop_wl1 = @loop_wl2 = nil
 | |
|     @opt = opt
 | |
| 
 | |
|     # [[name, [[r-1-1, r-1-2, ...], [r-2-1, r-2-2, ...]]], ...]
 | |
|     @results = []
 | |
| 
 | |
|     if @verbose
 | |
|       @start_time = Time.now
 | |
|       message @start_time
 | |
|       @execs.each_with_index{|(e, v), i|
 | |
|         message "target #{i}: #{v}"
 | |
|       }
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   def show_results
 | |
|     output
 | |
| 
 | |
|     if @verbose
 | |
|       message '-----------------------------------------------------------'
 | |
|       message 'raw data:'
 | |
|       message
 | |
|       message PP.pp(@results, "", 79)
 | |
|       message
 | |
|       message "Elapesed time: #{Time.now - @start_time} (sec)"
 | |
|     end
 | |
| 
 | |
|     output '-----------------------------------------------------------'
 | |
|     output 'benchmark results:'
 | |
| 
 | |
|     if @verbose and @repeat > 1
 | |
|       output "minimum results in each #{@repeat} measurements."
 | |
|     end
 | |
| 
 | |
|     output "name\t#{@execs.map{|(e, v)| v}.join("\t")}"
 | |
|     @results.each{|v, result|
 | |
|       rets = []
 | |
|       s = nil
 | |
|       result.each_with_index{|e, i|
 | |
|         r = e.min
 | |
|         case v
 | |
|         when /^vm1_/
 | |
|           if @loop_wl1
 | |
|             r -= @loop_wl1[i]
 | |
|             s = '*'
 | |
|           end
 | |
|         when /^vm2_/
 | |
|           if @loop_wl2
 | |
|             r -= @loop_wl2[i]
 | |
|             s = '*'
 | |
|           end
 | |
|         end
 | |
|         rets << sprintf("%.3f", r)
 | |
|       }
 | |
|       output "#{v}#{s}\t#{rets.join("\t")}"
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   def files
 | |
|     flag = {}
 | |
|     vm1 = vm2 = wl1 = wl2 = false
 | |
|     @files = Dir.glob(File.join(@dir, 'bm*.rb')).map{|file|
 | |
|       next if @pattern && /#{@pattern}/ !~ File.basename(file)
 | |
|       case file
 | |
|       when /bm_(vm[12])_/, /bm_loop_(whileloop2?).rb/
 | |
|         flag[$1] = true
 | |
|       end
 | |
|       file
 | |
|     }.compact
 | |
| 
 | |
|     if flag['vm1'] && !flag['whileloop']
 | |
|       @files << File.join(@dir, 'bm_loop_whileloop.rb')
 | |
|     elsif flag['vm2'] && !flag['whileloop2']
 | |
|       @files << File.join(@dir, 'bm_loop_whileloop2.rb')
 | |
|     end
 | |
| 
 | |
|     @files.sort!
 | |
|     progress_message "total: #{@files.size * @repeat} trial(s) (#{@repeat} trial(s) for #{@files.size} benchmark(s))\n"
 | |
|     @files
 | |
|   end
 | |
| 
 | |
|   def run
 | |
|     files.each_with_index{|file, i|
 | |
|       @i = i
 | |
|       r = measure_file(file)
 | |
| 
 | |
|       if /bm_loop_whileloop.rb/ =~ file
 | |
|         @loop_wl1 = r[1].map{|e| e.min}
 | |
|       elsif /bm_loop_whileloop2.rb/ =~ file
 | |
|         @loop_wl2 = r[1].map{|e| e.min}
 | |
|       end
 | |
|     }
 | |
|   end
 | |
| 
 | |
|   def measure_file file
 | |
|     name = File.basename(file, '.rb').sub(/^bm_/, '')
 | |
|     prepare_file = File.join(File.dirname(file), "prepare_#{name}.rb")
 | |
|     load prepare_file if FileTest.exist?(prepare_file)
 | |
| 
 | |
|     if @verbose
 | |
|       output
 | |
|       output '-----------------------------------------------------------'
 | |
|       output name
 | |
|       output
 | |
|       output File.read(file)
 | |
|       output
 | |
|     end
 | |
| 
 | |
|     result = [name]
 | |
|     result << @execs.map{|(e, v)|
 | |
|       (0...@repeat).map{
 | |
|         message_print "#{v}\t"
 | |
|         progress_message '.'
 | |
| 
 | |
|         m = measure(e, file)
 | |
|         message "#{m}"
 | |
|         m
 | |
|       }
 | |
|     }
 | |
|     @results << result
 | |
|     result
 | |
|   end
 | |
| 
 | |
|   def measure executable, file
 | |
|     cmd = "#{executable} #{file}"
 | |
|     m = Benchmark.measure{
 | |
|       `#{cmd}`
 | |
|     }
 | |
| 
 | |
|     if $? != 0
 | |
|       raise "Benchmark process exited with abnormal status (#{$?})"
 | |
|     end
 | |
| 
 | |
|     m.real
 | |
|   end
 | |
| end
 | |
| 
 | |
| if __FILE__ == $0
 | |
|   opt = {
 | |
|     :execs => ['ruby'],
 | |
|     :dir => './',
 | |
|     :repeat => 1,
 | |
|     :output => "bmlog-#{Time.now.strftime('%Y%m%d-%H%M%S')}.#{$$}",
 | |
|   }
 | |
| 
 | |
|   parser = OptionParser.new{|o|
 | |
|     o.on('-e', '--executables [EXECS]',
 | |
|          "Specify benchmark one or more targets. (exec1; exec2; exec3, ...)"){|e|
 | |
|       opt[:execs] = e.split(/;/)
 | |
|     }
 | |
|     o.on('-d', '--directory [DIRECTORY]', "Benchmark suites directory"){|d|
 | |
|       opt[:dir] = d
 | |
|     }
 | |
|     o.on('-p', '--pattern [PATTERN]', "Benchmark name pattern"){|p|
 | |
|       opt[:pattern] = p
 | |
|     }
 | |
|     o.on('-r', '--repeat-count [NUM]', "Repeat count"){|n|
 | |
|       opt[:repeat] = n.to_i
 | |
|     }
 | |
|     o.on('-o', '--output-file [FILE]', "Output file"){|o|
 | |
|       opt[:output] = o
 | |
|     }
 | |
|     o.on('-q', '--quiet', "Run without notify information except result table."){|q|
 | |
|       opt[:quiet] = q
 | |
|     }
 | |
|     o.on('-v', '--verbose'){|v|
 | |
|       opt[:verbose] = v
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   parser.parse!(ARGV)
 | |
|   BenchmarkDriver.benchmark(opt)
 | |
| end
 | |
| 
 |