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