#!/usr/bin/env ruby $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.join(File.dirname(__FILE__), 'src')) require 'slim' require 'complex_view' require 'benchmark' require 'ostruct' require 'erubis' require 'erb' require 'haml' require 'tilt' class SlimBenchmarks def initialize(slow, iterations) @iterations = (iterations || 1000).to_i @benches = [] tpl_erb = File.read(File.dirname(__FILE__) + '/src/complex.erb') tpl_haml = File.read(File.dirname(__FILE__) + '/src/complex.haml') tpl_slim = File.read(File.dirname(__FILE__) + '/src/complex.slim') view = ComplexView.new eview = OpenStruct.new(:header => view.header, :item => view.item).instance_eval{ binding } erb = ERB.new(tpl_erb) erubis = Erubis::Eruby.new(tpl_erb) fast_erubis = Erubis::FastEruby.new(tpl_erb) haml = Haml::Engine.new(tpl_haml, :format => :html5) haml_ugly = Haml::Engine.new(tpl_haml, :format => :html5, :ugly => true) slim = Slim::Template.new { tpl_slim } tilt_erb = Tilt::ERBTemplate.new { tpl_erb } tilt_erubis = Tilt::ErubisTemplate.new { tpl_erb } tilt_haml = Tilt::HamlTemplate.new(:format => :html5){ tpl_haml } tilt_haml_ugly = Tilt::HamlTemplate.new(:format => :html5, :ugly => true){ tpl_haml } tilt_slim = Slim::Template.new { tpl_slim } haml.def_method(view, :run_haml) haml_ugly.def_method(view, :run_haml_ugly) view.instance_eval %{ def run_erb; #{erb.src}; end def run_erubis; #{erubis.src}; end def run_fast_erubis; #{fast_erubis.src}; end def run_slim; #{slim.precompiled_template}; end } if slow bench('(1) erb') { ERB.new(tpl_erb).result(eview) } bench('(1) erubis') { Erubis::Eruby.new(tpl_erb).result(eview) } bench('(1) fast erubis') { Erubis::Eruby.new(tpl_erb).result(eview) } bench('(1) slim') { Slim::Template.new { tpl_slim }.render(view) } bench('(1) haml') { Haml::Engine.new(tpl_haml, :format => :html5).render(view) } bench('(1) haml ugly') { Haml::Engine.new(tpl_haml, :format => :html5, :ugly => true).render(view) } end bench('(2) erb') { erb.result(eview) } bench('(2) erubis') { erubis.result(eview) } bench('(2) fast erubis') { fast_erubis.result(eview) } bench('(2) slim') { slim.render(view) } bench('(2) haml') { haml.render(view) } bench('(2) haml ugly') { haml_ugly.render(view) } bench('(3) erb') { view.run_erb } bench('(3) erubis') { view.run_erubis } bench('(3) fast erubis') { view.run_fast_erubis } bench('(3) slim') { view.run_slim } bench('(3) haml') { view.run_haml } bench('(3) haml ugly') { view.run_haml_ugly } bench('(4) erb') { tilt_erb.render(view) } bench('(4) erubis') { tilt_erubis.render(view) } bench('(4) slim') { tilt_slim.render(view) } bench('(4) haml') { tilt_haml.render(view) } bench('(4) haml ugly') { tilt_haml_ugly.render(view) } end def run puts "#{@iterations} Iterations" Benchmark.bmbm do |x| @benches.each do |name, block| x.report name.to_s do @iterations.to_i.times { block.call } end end end puts " 1. Uncached benchmark. Template is parsed every time. Activate this benchmark with slow=1. 2. Cached benchmark. Template is parsed before the benchmark. The ruby code generated by the template engine might be evaluated every time. This benchmark uses the standard API of the template engine. 3. Compiled benchmark. Template is parsed before the benchmark and generated ruby code is compiled into a method. This is the fastest evaluation strategy because it benchmarks pure execution speed of the generated ruby code. 4. Compiled Tilt benchmark. Template is compiled with Tilt, which gives a more accurate result of the performance in production mode in frameworks like Sinatra, Ramaze and Camping. (Rails still uses its own template compilation.) " end def bench(name, &block) @benches.push([name, block]) end end SlimBenchmarks.new(ARGV[0], ARGV[1]).run