mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-29 07:05:12 -07:00
make theme_runner actually useful outside of the performance benchmarks
This commit is contained in:
@@ -3,7 +3,13 @@
|
|||||||
require 'benchmark/ips'
|
require 'benchmark/ips'
|
||||||
require_relative 'theme_runner'
|
require_relative 'theme_runner'
|
||||||
|
|
||||||
RubyVM::YJIT.enable if defined?(RubyVM::YJIT)
|
if defined?(RubyVM::YJIT)
|
||||||
|
RubyVM::YJIT.enable
|
||||||
|
puts "* YJIT enabled"
|
||||||
|
else
|
||||||
|
puts "* YJIT not enabled"
|
||||||
|
end
|
||||||
|
|
||||||
Liquid::Environment.default.error_mode = ARGV.first.to_sym if ARGV.first
|
Liquid::Environment.default.error_mode = ARGV.first.to_sym if ARGV.first
|
||||||
|
|
||||||
profiler = ThemeRunner.new
|
profiler = ThemeRunner.new
|
||||||
@@ -18,8 +24,8 @@ Benchmark.ips do |x|
|
|||||||
|
|
||||||
phase = ENV["PHASE"] || "all"
|
phase = ENV["PHASE"] || "all"
|
||||||
|
|
||||||
x.report("tokenize:") { profiler.tokenize } if phase == "all" || phase == "tokenize"
|
x.report("tokenize:") { profiler.tokenize_all } if phase == "all" || phase == "tokenize"
|
||||||
x.report("parse:") { profiler.compile } if phase == "all" || phase == "parse"
|
x.report("parse:") { profiler.compile_all } if phase == "all" || phase == "parse"
|
||||||
x.report("render:") { profiler.render } if phase == "all" || phase == "render"
|
x.report("render:") { profiler.render_all } if phase == "all" || phase == "render"
|
||||||
x.report("parse & render:") { profiler.run } if phase == "all" || phase == "run"
|
x.report("parse & render:") { profiler.run_all } if phase == "all" || phase == "run"
|
||||||
end
|
end
|
||||||
|
|||||||
+65
-58
@@ -26,22 +26,38 @@ class ThemeRunner
|
|||||||
# Initialize a new liquid ThemeRunner instance
|
# Initialize a new liquid ThemeRunner instance
|
||||||
# Will load all templates into memory, do this now so that we don't profile IO.
|
# Will load all templates into memory, do this now so that we don't profile IO.
|
||||||
def initialize
|
def initialize
|
||||||
@tests = Dir[__dir__ + '/tests/**/*.liquid'].collect do |test|
|
@tests = []
|
||||||
|
Dir[__dir__ + '/tests/**/*.liquid'].each do |test|
|
||||||
next if File.basename(test) == 'theme.liquid'
|
next if File.basename(test) == 'theme.liquid'
|
||||||
|
|
||||||
theme_path = File.dirname(test) + '/theme.liquid'
|
test_name = File.basename(File.dirname(test)) + "/" + File.basename(test)
|
||||||
{
|
theme_name = File.basename(File.dirname(test))
|
||||||
liquid: File.read(test),
|
template_name = File.basename(test)
|
||||||
layout: (File.file?(theme_path) ? File.read(theme_path) : nil),
|
layout_path = File.dirname(test) + '/theme.liquid'
|
||||||
template_name: test,
|
|
||||||
}
|
|
||||||
end.compact
|
|
||||||
|
|
||||||
compile_all_tests
|
test = {
|
||||||
|
test_name: test_name,
|
||||||
|
liquid: File.read(test),
|
||||||
|
layout: File.file?(layout_path) ? File.read(layout_path) : nil,
|
||||||
|
template_name: template_name,
|
||||||
|
theme_name: theme_name,
|
||||||
|
theme_path: File.realpath(File.dirname(test)),
|
||||||
|
}
|
||||||
|
|
||||||
|
@tests << test
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def find_test(test_name)
|
||||||
|
@tests.find do |test_hash|
|
||||||
|
test_hash[:test_name] == test_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :tests
|
||||||
|
|
||||||
# `compile` will test just the compilation portion of liquid without any templates
|
# `compile` will test just the compilation portion of liquid without any templates
|
||||||
def compile
|
def compile_all
|
||||||
@tests.each do |test_hash|
|
@tests.each do |test_hash|
|
||||||
Liquid::Template.new.parse(test_hash[:liquid])
|
Liquid::Template.new.parse(test_hash[:liquid])
|
||||||
Liquid::Template.new.parse(test_hash[:layout])
|
Liquid::Template.new.parse(test_hash[:layout])
|
||||||
@@ -49,7 +65,7 @@ class ThemeRunner
|
|||||||
end
|
end
|
||||||
|
|
||||||
# `tokenize` will just test the tokenizen portion of liquid without any templates
|
# `tokenize` will just test the tokenizen portion of liquid without any templates
|
||||||
def tokenize
|
def tokenize_all
|
||||||
ss = StringScanner.new("")
|
ss = StringScanner.new("")
|
||||||
@tests.each do |test_hash|
|
@tests.each do |test_hash|
|
||||||
tokenizer = Liquid::Tokenizer.new(
|
tokenizer = Liquid::Tokenizer.new(
|
||||||
@@ -62,78 +78,69 @@ class ThemeRunner
|
|||||||
end
|
end
|
||||||
|
|
||||||
# `run` is called to benchmark rendering and compiling at the same time
|
# `run` is called to benchmark rendering and compiling at the same time
|
||||||
def run
|
def run_all
|
||||||
each_test do |liquid, layout, assigns, page_template, template_name|
|
@tests.each do |test|
|
||||||
compile_and_render(liquid, layout, assigns, page_template, template_name)
|
compile_and_render(test)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# `render` is called to benchmark just the render portion of liquid
|
# `render` is called to benchmark just the render portion of liquid
|
||||||
def render
|
def render_all
|
||||||
|
@compiled_tests ||= compile_all_tests
|
||||||
@compiled_tests.each do |test|
|
@compiled_tests.each do |test|
|
||||||
tmpl = test[:tmpl]
|
render_template(test)
|
||||||
assigns = test[:assigns]
|
|
||||||
layout = test[:layout]
|
|
||||||
|
|
||||||
if layout
|
|
||||||
assigns['content_for_layout'] = tmpl.render!(assigns)
|
|
||||||
layout.render!(assigns)
|
|
||||||
else
|
|
||||||
tmpl.render!(assigns)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def run_one_test(test_name)
|
||||||
|
test = find_test(test_name)
|
||||||
|
compile_and_render(test)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def render_layout(template, layout, assigns)
|
def render_template(compiled_test)
|
||||||
assigns['content_for_layout'] = template.render!(assigns)
|
tmpl, assigns, layout = compiled_test.values_at(:tmpl, :assigns, :layout)
|
||||||
layout&.render!(assigns)
|
if layout
|
||||||
|
assigns['content_for_layout'] = tmpl.render!(assigns)
|
||||||
|
layout.render!(assigns)
|
||||||
|
else
|
||||||
|
tmpl.render!(assigns)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile_and_render(template, layout, assigns, page_template, template_file)
|
def compile_and_render(test)
|
||||||
compiled_test = compile_test(template, layout, assigns, page_template, template_file)
|
compiled_test = compile_test(test[:liquid], test[:layout], test[:template_name], test[:theme_path])
|
||||||
render_layout(compiled_test[:tmpl], compiled_test[:layout], compiled_test[:assigns])
|
render_template(compiled_test)
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile_all_tests
|
def compile_all_tests
|
||||||
@compiled_tests = []
|
@compiled_tests = []
|
||||||
each_test do |liquid, layout, assigns, page_template, template_name|
|
@tests.each do |test_hash|
|
||||||
@compiled_tests << compile_test(liquid, layout, assigns, page_template, template_name)
|
@compiled_tests << compile_test(
|
||||||
|
test_hash[:liquid],
|
||||||
|
test_hash[:layout],
|
||||||
|
test_hash[:template_name],
|
||||||
|
test_hash[:theme_path],
|
||||||
|
)
|
||||||
end
|
end
|
||||||
@compiled_tests
|
@compiled_tests
|
||||||
end
|
end
|
||||||
|
|
||||||
def compile_test(template, layout, assigns, page_template, template_file)
|
def compile_test(template, layout, template_name, theme_path)
|
||||||
tmpl = init_template(page_template, template_file)
|
tmpl = Liquid::Template.new
|
||||||
parsed_template = tmpl.parse(template).dup
|
tmpl.assigns['page_title'] = 'Page title'
|
||||||
|
tmpl.assigns['template'] = template_name
|
||||||
|
tmpl.registers[:file_system] = ThemeRunner::FileSystem.new(theme_path)
|
||||||
|
|
||||||
|
parsed_template = tmpl.parse(template)
|
||||||
|
|
||||||
|
assigns = Database.tables.dup
|
||||||
if layout
|
if layout
|
||||||
parsed_layout = tmpl.parse(layout)
|
parsed_layout = tmpl.parse(layout).dup
|
||||||
{ tmpl: parsed_template, assigns: assigns, layout: parsed_layout }
|
{ tmpl: parsed_template, assigns: assigns, layout: parsed_layout }
|
||||||
else
|
else
|
||||||
{ tmpl: parsed_template, assigns: assigns }
|
{ tmpl: parsed_template, assigns: assigns }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# utility method with similar functionality needed in `compile_all_tests` and `run`
|
|
||||||
def each_test
|
|
||||||
# Dup assigns because will make some changes to them
|
|
||||||
assigns = Database.tables.dup
|
|
||||||
|
|
||||||
@tests.each do |test_hash|
|
|
||||||
# Compute page_template outside of profiler run, uninteresting to profiler
|
|
||||||
page_template = File.basename(test_hash[:template_name], File.extname(test_hash[:template_name]))
|
|
||||||
yield(test_hash[:liquid], test_hash[:layout], assigns, page_template, test_hash[:template_name])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# set up a new Liquid::Template object for use in `compile_and_render` and `compile_test`
|
|
||||||
def init_template(page_template, template_file)
|
|
||||||
tmpl = Liquid::Template.new
|
|
||||||
tmpl.assigns['page_title'] = 'Page title'
|
|
||||||
tmpl.assigns['template'] = page_template
|
|
||||||
tmpl.registers[:file_system] = ThemeRunner::FileSystem.new(File.dirname(template_file))
|
|
||||||
tmpl
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user