Files
liquid/performance/theme_runner.rb
Tobias Lütke 7dcf578898 Replace regexpes with Ragel grammer
context parsing was handrolled and pretty ad-hoc
this branch exists to explore parsing the context
through a defined fsm as produced by Ragel
2013-03-19 18:30:08 -04:00

112 lines
3.4 KiB
Ruby

# This profiler run simulates Shopify.
# We are looking in the tests directory for liquid files and render them within the designated layout file.
# We will also export a substantial database to liquid which the templates can render values of.
# All this is to make the benchmark as non syntetic as possible. All templates and tests are lifted from
# direct real-world usage and the profiler measures code that looks very similar to the way it looks in
# Shopify which is likely the biggest user of liquid in the world which something to the tune of several
# million Template#render calls a day.
require 'rubygems'
require 'active_support'
require 'yaml'
require 'digest/md5'
require File.dirname(__FILE__) + '/shopify/liquid'
require File.dirname(__FILE__) + '/shopify/database.rb'
class ThemeRunner
# Load all templates into memory, do this now so that
# we don't profile IO.
def initialize
@tests = Dir[File.dirname(__FILE__) + '/tests/**/*.liquid'].collect do |test|
next if File.basename(test) == 'theme.liquid'
theme_path = File.dirname(test) + '/theme.liquid'
[Liquid::Template.parse(File.read(test)), File.file?(theme_path) ? Liquid::Template.parse(File.read(theme_path)) : nil, test]
end.compact
end
def compile
# Dup assigns because will make some changes to them
@tests.each do |liquid, layout, template_name|
tmpl = Liquid::Template.new
tmpl.parse(liquid)
tmpl = Liquid::Template.new
tmpl.parse(layout)
end
end
def run
# Dup assigns because will make some changes to them
assigns = Database.tables.dup
@tests.each do |liquid, layout, template_name|
# Compute page_tempalte outside of profiler run, uninteresting to profiler
page_template = File.basename(template_name, File.extname(template_name))
compile_and_render(liquid, layout, assigns, page_template)
end
end
<<<<<<< HEAD
def run_profile
RubyProf.measure_mode = RubyProf::WALL_TIME
=======
def run(profile = false)
RubyProf.measure_mode = RubyProf::WALL_TIME if profile
>>>>>>> wip
# Dup assigns because will make some changes to them
assigns = Database.tables.dup
assigns['page_title'] = 'Page title'
@tests.each do |liquid, layout, template_name|
# Compute page_tempalte outside of profiler run, uninteresting to profiler
html = nil
page_template = File.basename(template_name, File.extname(template_name))
unless @started
if profile
RubyProf.start
RubyProf.pause
end
@started = true
end
assigns['template'] = page_template
RubyProf.resume if profile
html = render(liquid, layout, assigns)
RubyProf.pause if profile
# return the result and the MD5 of the content, this can be used to detect regressions between liquid version
$stdout.puts "* rendered template %s, content: %s" % [template_name, Digest::MD5.hexdigest(html)]
# Uncomment to dump html files to /tmp so that you can inspect for errors
# File.open("/tmp/#{File.basename(template_name)}.html", "w+") { |fp| fp <<html}
end
RubyProf.stop if profile
end
def render(template, layout, assigns)
content_for_layout = template.render(assigns)
if layout
assigns['content_for_layout'] = content_for_layout
layout.render(assigns)
else
content_for_layout
end
end
end