#!/usr/bin/env ruby ### ### $Release: 2.6.5 $ ### copyright(c) 2006-2009 kuwata-lab.com all rights reserved. ### require 'erb' require 'erubis' require 'erubis/tiny' require 'erubis/engine/enhanced' require 'yaml' require 'cgi' include ERB::Util begin require 'eruby' rescue LoadError ERuby = nil end def File.write(filename, content) File.open(filename, 'w') { |f| f.write(content) } end ## change benchmark library to use $stderr instead of $stdout require 'benchmark' module Benchmark class Report def print(*args) $stderr.print(*args) end end module_function def print(*args) $stderr.print(*args) end end class BenchmarkApplication TARGETS = %w[eruby ERB ERB(cached) Erubis::Eruby Erubis::Eruby(cached) Erubis::FastEruby Erubis::FastEruby(cached) Erubis::TinyEruby Erubis::ArrayBufferEruby Erubis::PrintOutEruby Erubis::StdoutEruby ] def initialize(ntimes, context, targets=nil, params={}) @ntimes = ntimes @context = context @targets = targets && !targets.empty? ? targets : TARGETS.dup @testmode = params[:testmode] || 'execute' @erubyfile = params[:erubyfile] || 'erubybench.rhtml' @printout = params[:printout] || false end attr_accessor :ntimes, :targets attr_accessor :testmode, :erubyfile, :contextfile, :printout def context2code(context, varname='context') s = '' context.each { |k, | s << "#{k} = #{varname}[#{k.inspect}]; " } return s end def perform_benchmark width = 30 $stderr.puts "*** ntimes=#{@ntimes}, testmode=#{@testmode}" Benchmark.bm(width) do |job| for target in @targets do method = "#{@testmode}_#{target.gsub(/::|-|\(/, '_').gsub(/\)/, '').downcase}" #$stderr.puts "*** debug: method=#{method.inspect}" next unless self.respond_to?(method) filename = "bench_#{(target =~ /^(\w+)/) && $1.downcase}.rhtml" title = target output = nil job.report(title) do output = self.__send__(method, filename, @context) end File.write("output.#{target.gsub(/[^\w]/,'')}", output) if @printout && output && !output.empty? end end end ## def execute_eruby(filename, context) return unless ERuby #eval context2code(context) list = context['list'] @ntimes.times do ERuby.import(filename) end return nil end def execute_erb(filename, context) #eval context2code(context) list = context['list'] output = nil @ntimes.times do eruby = ERB.new(File.read(filename)) output = eruby.result(binding()) print output end return output end def execute_erb_cached(filename, context) #eval context2code(context) list = context['list'] output = nil cachefile = filename + '.cache' File.unlink(cachefile) if test(?f, cachefile) @ntimes.times do if !test(?f, cachefile) || File.mtime(filename) > File.mtime(cachefile) eruby = ERB.new(File.read(filename)) File.write(cachefile, eruby.src) else eruby = ERB.new('') #eruby.src = File.read(cachefile) eruby.instance_variable_set("@src", File.read(cachefile)) end output = eruby.result(binding()) print output end return output end ## no cached for klass in %w[Eruby FastEruby TinyEruby ArrayBufferEruby PrintOutEruby StdoutEruby] do s = <<-END def execute_erubis_#{klass.downcase}(filename, context) #eval context2code(context) list = context['list'] output = nil @ntimes.times do eruby = Erubis::#{klass}.new(File.read(filename)) output = eruby.result(binding()) print output end return output end END eval s end ## cached for klass in %w[Eruby FastEruby] do s = <<-END def execute_erubis_#{klass.downcase}_cached(filename, context) #eval context2code(context) list = context['list'] cachefile = filename + '.cache' File.unlink(cachefile) if test(?f, cachefile) output = nil @ntimes.times do eruby = Erubis::#{klass}.load_file(filename) output = eruby.result(binding()) print output end savefile = cachefile.sub(/\\.cache$/, '.#{klass.downcase}.cache') File.rename(cachefile, savefile) return output end END eval s end ## def convert_eruby(filename, context) return unless ERuby #eval context2code(context) list = context['list'] output = nil @ntimes.times do output = ERuby::Compiler.new.compile_string(File.read(filename)) end return output end def convert_erb(filename, context) #eval context2code(context) list = context['list'] output = nil @ntimes.times do eruby = ERB.new(File.read(filename)) output = eruby.src end return output end for klass in %w[Eruby FastEruby TinyEruby] s = <<-END def convert_erubis_#{klass.downcase}(filename, context) #eval context2code(context) list = context['list'] output = nil @ntimes.times do eruby = Erubis::#{klass}.new(File.read(filename)) output = eruby.src end return output end END eval s end end require 'optparse' class MainApplication def parse_argv(argv=ARGV) optparser = OptionParser.new options = {} ['-h', '-n N', '-t erubyfile', '-f contextfile', '-A', '-e', '-x exclude', '-m testmode', '-X', '-p', '-D'].each do |opt| optparser.on(opt) { |val| options[opt[1].chr] = val } end begin targets = optparser.parse!(argv) rescue => ex $stderr.puts "#{@script}: #{ex.to_s}" exit(1) end return options, targets end def execute @script = File.basename($0) ntimes = 1000 targets = BenchmarkApplication::TARGETS.dup testmode = 'execute' contextfile = 'bench_context.yaml' # options, args = parse_argv(ARGV) ntimes = options['n'].to_i if options['n'] targets = args if args && !args.empty? targets = targets - options['x'].split(/,/) if options['x'] testmode = options['m'] if options['m'] contextfile = options['f'] if options['f'] erubyfile = options['t'] if options['t'] # if options['h'] $stderr.puts "Usage: ruby #{@script} [..options..] [..targets..]" $stderr.puts " -h : help" $stderr.puts " -n N : loop N times" $stderr.puts " -f datafile : context data filename (*.yaml)" $stderr.puts " -x exclude : exclude target name" $stdout.puts " -m testmode : 'execute' or 'convert' (default 'execute')" $stderr.puts " -p : print output to file (filename: 'output.TARGETNAME')" return end # #if ! options['t'] for item in %w[eruby erb erubis] fname = "bench_#{item}.rhtml" header = File.read("templates/_header.html") #body = File.read("templates/#{erubyfile}") body = File.read("templates/#{fname}") footer = File.read("templates/_footer.html") content = header + body + footer File.write(fname, content) end # if options['e'] # escape tuples = [ [ 'bench_eruby.rhtml', '<%= CGI.escapeHTML((\1).to_s) %>' ], [ 'bench_erb.rhtml', '<%=h \1 %>' ], [ 'bench_erubis.rhtml', '<%== \1 %>' ], ] for fname, replace in tuples content = File.read(fname).gsub(/<%= ?(.*?) ?%>/, replace) File.write(fname, content) end targets.delete('Erubis::TinyEruby') ## because TinyEruby doesn't support '<%== =>' end # context = YAML.load_file(contextfile) # params = { :printout=>options['p'], :testmode=>testmode, } app = BenchmarkApplication.new(ntimes, context, targets, params) app.perform_benchmark() end end if __FILE__ == $0 ## open /dev/null $stdout = File.open('/dev/null', 'w') at_exit do $stdout.close() end ## start benchmark MainApplication.new().execute() end