working on optimization

This commit is contained in:
dinedine 2010-08-09 15:51:27 +02:00
parent fbda6a17f9
commit d879b80b7a
4 changed files with 93 additions and 15 deletions

View File

@ -1,6 +1,50 @@
class Layout < LiquidTemplate class Layout < LiquidTemplate
## fields ##
# field :blocks, :type => Hash
# def unmarshalled_blocks
# # puts "self.blocks = #{self.blocks.class.inspect}"
# @unmarshalled_blocks ||= self.blocks.inject({}) do |b, (name, node)|
# # puts "b= #{b.inspect} / name = #{name.inspect} / node = #{node.inspect}"
# b[name] = Marshal.load(node)
# b
# end
# end
protected
def after_parse_template
blocks = self.find_blocks(self.template.root)
self.template.send(:instance_variable_set, :"@parent_blocks", blocks)
# TODO: include parent blocks in self.template before marshalling it
# puts "[Layout / blocks] #{self.blocks.inspect}"
end
def find_blocks(node, blocks = {})
# puts "[Layout/#{self.slug}] ** find_blocks #{node.class.inspect} / #{blocks.keys.inspect}"
if node.respond_to?(:nodelist) && node.nodelist
# puts " ==> find_blocks nodelist = #{node.nodelist.inspect}"
node.nodelist.inject(blocks) do |b, node|
if node.is_a?(Locomotive::Liquid::Tags::Block)
# b[node.name] = Marshal.dump(node)
b[node.name] = node
end
# else
self.find_blocks(node, b) # FIXME: add nested blocks
# end
b
end
end
blocks
end
## associations ## ## associations ##
# references_many :pages # references_many :pages
# embeds_many :parts, :class_name => 'PagePart' # embeds_many :parts, :class_name => 'PagePart'

View File

@ -37,15 +37,25 @@ module Locomotive
module InstanceMethods module InstanceMethods
def template def template
Marshal.load(read_attribute(:serialized_template).to_s) rescue nil @template ||= Marshal.load(read_attribute(:serialized_template).to_s) rescue nil
end end
protected protected
def store_template def store_template
begin begin
template = ::Liquid::Template.parse(self.liquify_template_source) @template = ::Liquid::Template.parse(self.liquify_template_source)
self.serialized_template = BSON::Binary.new(Marshal.dump(template))
if self.respond_to?(:after_parse_template) # kind of callback
self.send(:after_parse_template)
end
self.serialized_template = BSON::Binary.new(Marshal.dump(@template))
if self.respond_to?(:after_store_template) # kind of callback
self.send(:after_store_template)
end
rescue ::Liquid::SyntaxError => error rescue ::Liquid::SyntaxError => error
self.errors.add :template, :liquid_syntax_error self.errors.add :template, :liquid_syntax_error
end end

View File

@ -4,6 +4,8 @@ module Locomotive
class Extends < ::Liquid::Block class Extends < ::Liquid::Block
Syntax = /(#{::Liquid::QuotedFragment})/ Syntax = /(#{::Liquid::QuotedFragment})/
# attr_accessor :blocks
def initialize(tag_name, markup, tokens) def initialize(tag_name, markup, tokens)
if markup =~ Syntax if markup =~ Syntax
@template_name = $1 @template_name = $1
@ -17,25 +19,35 @@ module Locomotive
m[node.name] = node if node.is_a?(Locomotive::Liquid::Tags::Block); m m[node.name] = node if node.is_a?(Locomotive::Liquid::Tags::Block); m
end end
# puts "** Extends #{@template_name} / #{@blocks.inspect} / #{@nodelist.inspect}" # puts "\n** initialize ** Extends #{@template_name} / #{@blocks.inspect}"
end end
def parse(tokens) def parse(tokens)
# puts "[#{@template_name}] parsing...#{tokens.inspect}"
parse_all(tokens) parse_all(tokens)
end end
def render(context) def render(context)
template = load_template(context) if OPTIMIZATION
parent_blocks = find_blocks(template.root) template, parent_blocks = load_template(context)
else
template = load_template(context)
parent_blocks = find_blocks(template.root)
end
# puts "** [Extends/render] parent_blocks = #{parent_blocks.inspect}" # puts "** [Extends/render] @blocks = #{@blocks.inspect} / @nodelist = #{@nodelist.inspect} / parent_blocks = #{parent_blocks.inspect}"
# BUG: parent blocks and parent template blocks are disconnected (OPTIMIZATION). need to resync them along with @nodelist
@blocks.each do |name, block| @blocks.each do |name, block|
# puts "** [Extends/render] #{name}, #{block.inspect}" # puts "** [Extends/render] #{name}, #{block.inspect}"
if pb = parent_blocks[name] if pb = parent_blocks[name]
# puts "[#{name}]...found parent block ! #{pb.inspect}"
pb.parent = block.parent pb.parent = block.parent
# puts "[#{name}] pb.parent = #{pb.parent.inspect} / block.parent = #{block.parent.inspect}"
pb.add_parent(pb.nodelist) pb.add_parent(pb.nodelist)
# puts "[#{name}] pb.nodelist = #{pb.nodelist.inspect}"
pb.nodelist = block.nodelist pb.nodelist = block.nodelist
# puts "[#{name}] block.nodelist = #{block.nodelist.inspect}"
else else
if is_extending?(template) if is_extending?(template)
template.root.nodelist << block template.root.nodelist << block
@ -83,7 +95,12 @@ module Locomotive
def load_template(context) def load_template(context)
# puts "** load_template (#{context[@template_name]})" # puts "** load_template (#{context[@template_name]})"
layout = context.registers[:site].layouts.where(:slug => context[@template_name]).first layout = context.registers[:site].layouts.where(:slug => context[@template_name]).first
layout.template if OPTIMIZATION
# [layout.template, layout.unmarshalled_blocks]
[layout.template, layout.template.send(:instance_variable_get, :"@parent_blocks")]
else
layout.template
end
end end
def find_blocks(node, blocks={}) def find_blocks(node, blocks={})

View File

@ -9,6 +9,8 @@ require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_
# config.master = Mongo::Connection.new.db("locomotive_perf_test") # config.master = Mongo::Connection.new.db("locomotive_perf_test")
# end # end
OPTIMIZATION = false
%w{sites pages layouts}.each do |collection| %w{sites pages layouts}.each do |collection|
Mongoid.master.collection(collection).drop Mongoid.master.collection(collection).drop
end end
@ -35,13 +37,15 @@ layout_with_sidebar = site.layouts.create :name => 'with_sidebar', :value => %{
</html> </html>
} }
# puts layout_with_sidebar.unmarshalled_blocks.inspect
custom_layout_with_sidebar = site.layouts.create :name => 'custom_with_sidebar', :value => %{ custom_layout_with_sidebar = site.layouts.create :name => 'custom_with_sidebar', :value => %{
\{% extends 'with_sidebar' %\} \{% extends 'with_sidebar' %\}
\{% block sidebar %\}A sidebar here\{% endblock %\} \{% block sidebar %\}A sidebar here\{% endblock %\}
\{% block body %\}<div class="wrapper">\{% block main %\}DEFAULT MAIN CONTENT\{% endblock %\}</div>\{% endblock %\} \{% block body %\}<div class="wrapper">\{% block main %\}DEFAULT MAIN CONTENT\{% endblock %\}</div>\{% endblock %\}
} }
page = site.pages.create :title => 'Index', :slug => 'index', :layout_template => %{ page = site.pages.create :title => 'Benchmark', :slug => 'benchmark', :layout_template => %{
\{% extends 'custom_with_sidebar' %\} \{% extends 'custom_with_sidebar' %\}
\{% block sidebar %\}\{\{ block.super \}\} / INDEX sidebar\{% endblock %\} \{% block sidebar %\}\{\{ block.super \}\} / INDEX sidebar\{% endblock %\}
\{% block main %\}Lorem ipsum\{% endblock %\} \{% block main %\}Lorem ipsum\{% endblock %\}
@ -49,18 +53,21 @@ page = site.pages.create :title => 'Index', :slug => 'index', :layout_template =
context = Liquid::Context.new({}, { 'site' => site }, { :site => site }) context = Liquid::Context.new({}, { 'site' => site }, { :site => site })
puts "====> \n#{page.render(context)}" puts "====> OUTPUT \n#{page.render(context)}"
Benchmark.bm do |bm| Benchmark.bm do |bm|
bm.report("Rendering page 10k times") do bm.report("Rendering page 10k times") do
10000.times do 10000.times do
Page.first.render(context) Page.last.render(context)
end end
end end
end end
# without liquify (macbook white): User System Total Real # # empty page (imac 27'): User System Total Real
# Rendering page 10k times 22.650000 6.220000 28.870000 ( 30.294338) # # Rendering page 10k times 13.390000 1.700000 15.090000 ( 15.654966)
# without liquify (imac 27'): User System Total Real # # page with inherited template (imac 27'): User System Total Real
# Rendering page 10k times 13.390000 1.700000 15.090000 ( 15.654966) # Rendering page 10k times 85.840000 7.600000 93.440000 ( 97.841248)
# # with optimization (imac 27'): User System Total Real
# Rendering page 10k times 84.240000 7.280000 91.520000 ( 95.475565)