Project

General

Profile

Backport #4115

Updated by jeremyevans0 (Jeremy Evans) over 5 years ago

=begin 
  
  ERB can be made faster by pushing all string fragments onto an array and then performing one join to make the result, rather than concatenating each string fragment.    This illustrates the patch: 
 
    [erb_benchmark.rb] 
    require 'benchmark' 
    require 'erb' 
 
    class FasterERB < ERB 
      def set_eoutvar(compiler, eoutvar = '_erbout') 
        compiler.put_cmd = "#{eoutvar}<<" 
        compiler.insert_cmd = "#{eoutvar}<<" 
 
        cmd = [] 
        cmd.push "#{eoutvar} = []" 
   
        compiler.pre_cmd = cmd 
 
        cmd = [] 
        cmd.push "#{eoutvar}.join" 
 
        compiler.post_cmd = cmd 
      end 
    end 
 
    Benchmark.bm(30) do |x| 
      n = 10 
      template = %q{got <%= "value" %> } 
 
      erb    = ERB.new template 
      frb = FasterERB.new template 
 
      x.report "#{n}k small" do 
        (1000 * n).times { erb.result } 
      end 
 
      x.report "#{n}k small (fast)" do 
        (1000 * n).times { frb.result } 
      end 
 
      erb = ERB.new(template * 100) 
      frb = FasterERB.new(template * 100) 
 
      x.report "#{n}k large" do 
        (1000 * n).times { erb.result } 
      end 
 
      x.report "#{n}k large (fast)" do 
        (1000 * n).times { frb.result } 
      end 
     
      if erb.result == frb.result 
        puts "outputs are equal" 
      end 
    end 
 
  As an example: 
 
    % ruby --version 
    ruby 1.8.7 (2009-06-12 patchlevel 174) [universal-darwin10.0] 
    % ruby erb_benchmark.rb  
                              user       system        total          real 
    10k small               0.170000     0.000000     0.170000 (    0.163556) 
    10k small (fast)        0.150000     0.000000     0.150000 (    0.153408) 
    10k large               6.560000     0.020000     6.580000 (    6.579351) 
    10k large (fast)        5.690000     0.010000     5.700000 (    5.703097) 
    outputs are equal 
 
  I attempted to make up a proper patch but I'm unfamiliar with the repository.    I wasn't sure how to run the tests, etc.    Obviously the patch simply consists of replacing the set_eoutvar method. 
 
  Note that on 1.9.3 it looks like you would also have to force the encoding of the final string. 
 
    cmd.push "#{eoutvar}.join.force_encoding(__ENCODING__)" 
 
 =end 
 

Back