Created
October 17, 2008 22:41
-
-
Save dcolthorp/17553 to your computer and use it in GitHub Desktop.
prototype of efficient inline template expansion
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Prototype of a mechanism for efficient inline template compilation | |
| # via call site caching. | |
| require 'merb-core' | |
| require 'merb-haml' | |
| END { | |
| require 'rbench' | |
| expando = Expando.new | |
| # make sure that the different methods are generating the same output for the sake of fairness | |
| raise "haml's not fair" unless expando.efficient_haml == expando.naive_haml | |
| raise "erb's not fair" unless expando.efficient_erb == expando.naive_erb | |
| # Compare this approach to inline use of haml or erubis | |
| # Results on my machine: | |
| # | naive | efficient | naive/expand | | |
| # ----------------------------------------------------------- | |
| # haml x10000 | 2.642 | 0.652 | 4.05x | | |
| # erb x10000 | 1.393 | 0.443 | 3.15x | | |
| RBench.run(10_000) do | |
| column :times | |
| column :naive, :title => "naive" | |
| column :expand, :title => "efficient" | |
| column :diff, :title => "naive/expand", :compare => [:naive,:expand] | |
| report "haml" do | |
| expand do | |
| expando.efficient_haml | |
| end | |
| naive do | |
| expando.naive_haml | |
| end | |
| end | |
| report "erb" do | |
| expand do | |
| expando.efficient_erb | |
| end | |
| naive do | |
| expando.naive_erb | |
| end | |
| end | |
| end | |
| } | |
| ################################################################### | |
| module Templatizer | |
| FakeIo = Struct.new :read, :path | |
| def expand_static_template(type, string, values={}) | |
| context = caller[0] | |
| mname = :"__expanded__#{context.gsub(%r{\W}, '_')}" | |
| extend ::Merb::InlineTemplates | |
| unless respond_to? mname | |
| string = _dedent string | |
| io = FakeIo.new string, context.scan(/.*?:\d+/).first | |
| Merb::Template.engine_for(".#{type}").compile_template(io, mname, values.keys, ::Merb::InlineTemplates) | |
| end | |
| send(mname, values) | |
| end | |
| def _dedent string | |
| min_size = Float::MAX | |
| string.scan(/^( *)\S/).each do |indentation, ignored| | |
| min_size = [min_size, indentation.length].min | |
| end | |
| string.gsub(/^ {0,#{min_size}}/, '') | |
| end | |
| end | |
| class Object | |
| include Templatizer | |
| end | |
| ################################################################### | |
| class Expando | |
| def initialize | |
| @instance = "YO" | |
| end | |
| def efficient_haml | |
| expand_static_template(:haml, <<-HAML, :a => 1) | |
| = @instance | |
| = a | |
| HAML | |
| end | |
| def naive_haml | |
| # Not fair to dedent here. | |
| haml = Haml::Engine.new <<-EOS | |
| = @instance | |
| = a | |
| EOS | |
| haml.render self, :a => 1 | |
| end | |
| def efficient_erb | |
| expand_static_template(:erb, <<-ERB, :a => 1) | |
| <%= @instance %> | |
| <%= a %> | |
| ERB | |
| end | |
| def naive_erb | |
| # Not fair to dedent here. | |
| eruby = ::Erubis::BlockAwareEruby.new(<<-ERB) | |
| <%= @instance %> | |
| <%= @a %> | |
| ERB | |
| eruby.evaluate :a => 1, :instance => @instance | |
| end | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment