working on optimization
This commit is contained in:
parent
fbda6a17f9
commit
d879b80b7a
@ -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'
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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={})
|
||||||
|
@ -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)
|
||||||
|
Loading…
Reference in New Issue
Block a user