Skip to content

Instantly share code, notes, and snippets.

@dcolthorp
Created October 17, 2008 22:41
Show Gist options
  • Select an option

  • Save dcolthorp/17553 to your computer and use it in GitHub Desktop.

Select an option

Save dcolthorp/17553 to your computer and use it in GitHub Desktop.
prototype of efficient inline template expansion
# 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