diff --git a/performance/unit/hybrid_render_benchmark.rb b/performance/unit/hybrid_render_benchmark.rb
index f52fc3ba..1fdae6a4 100644
--- a/performance/unit/hybrid_render_benchmark.rb
+++ b/performance/unit/hybrid_render_benchmark.rb
@@ -16,6 +16,8 @@ MULTIPLE_SELF_CLOSING = (1..20).map { |i| "{% render 'snippet_#{i}' %}" }.join("
BLOCK_FORM = "{% render 'snippet' %}Hello, world!{% endrender %}"
+BLOCK_FORM_20X = (1..20).map { |i| "{% render 'snippet_#{i}' %}content #{i}{% endrender %}" }.join("\n")
+
MIXED_TEMPLATE = <<~LIQUID
{% assign title = 'Hello' %}
{% render 'header' %}
@@ -28,12 +30,117 @@ LIQUID
LONG_TAIL = "{% render 'snippet' %}\n" + (1..100).map { |i| "{% assign x#{i} = #{i} %}" }.join("\n")
+NESTED_CONDITIONALS = <<~LIQUID
+ {% if customer %}
+ {% if customer.name %}
+
{{ customer.name }}
+ {% else %}
+ Guest
+ {% endif %}
+ {% if customer.vip %}
+ VIP
+ {% endif %}
+ {% else %}
+ {% if template == 'index' %}
+ Welcome
+ {% endif %}
+ {% endif %}
+LIQUID
+
+LOOP_HEAVY = <<~LIQUID
+ {% for product in collection.products %}
+
+
{{ product.title }}
+
{{ product.price | money }}
+ {% if product.available %}
+
+ {% else %}
+
+ {% endif %}
+
+ {% endfor %}
+ {% for tag in collection.tags %}
+ {{ tag }}
+ {% endfor %}
+ {% if paginate.pages > 1 %}
+
+ {% endif %}
+LIQUID
+
+CONTROL_FLOW_NO_RENDER = <<~LIQUID
+ {% case template %}
+ {% when 'product' %}
+ {% for block in section.blocks %}
+ {% if block.type == 'title' %}
+ {{ product.title }}
+ {% elsif block.type == 'price' %}
+ {{ product.price | money }}
+ {% elsif block.type == 'description' %}
+ {{ product.description }}
+ {% endif %}
+ {% endfor %}
+ {% when 'collection' %}
+ {% for product in collection.products %}
+ {% if product.available %}
+ {{ product.title }}
+ {% endif %}
+ {% endfor %}
+ {% when 'index' %}
+ {% for section in page.sections %}
+ {{ section.content }}
+ {% endfor %}
+ {% endcase %}
+LIQUID
+
+SINGLE_RENDER_AMONG_BLOCKS = <<~LIQUID
+ {% if settings.show_header %}
+ {% render 'header' %}
+ {% endif %}
+ {% for product in collection.products %}
+
+
{{ product.title }}
+ {% if product.compare_at_price > product.price %}
+ {{ product.compare_at_price | money }}
+ {% endif %}
+ {% if product.available %}
+
+ {% else %}
+ Sold out
+ {% endif %}
+
+ {% endfor %}
+ {% if paginate.pages > 1 %}
+
+ {% endif %}
+LIQUID
+
+RENDER_AMONG_50_BLOCKS = begin
+ opens = (1..25).map { |i| "#{" " * i}{% if cond_#{i} %}" }.join("\n")
+ closes = (1..25).map { |i| "#{" " * (26 - i)}{% endif %}" }.join("\n")
+ <<~LIQUID
+ {% for item in collection %}
+ #{opens}
+ #{" " * 26}{% render 'deep_snippet' %}
+ #{closes}
+ {% endfor %}
+ LIQUID
+end
+
+INTERLEAVED_RENDERS_AND_BLOCKS = (1..20).map { |i| "{% if cond_#{i} %}\n {% render 'snippet_#{i}' %}\n{% endif %}" }.join("\n")
+
TEMPLATES = {
"single self-closing render" => SINGLE_SELF_CLOSING,
"20x consecutive self-closing renders" => MULTIPLE_SELF_CLOSING,
"block-form render" => BLOCK_FORM,
"mixed template (self-closing + other tags)" => MIXED_TEMPLATE,
"self-closing render + 100 trailing tags" => LONG_TAIL,
+ "nested conditionals (0 renders, 6 end tags)" => NESTED_CONDITIONALS,
+ "loop-heavy (0 renders, 5 end tags)" => LOOP_HEAVY,
+ "control flow (0 renders, 10 end tags)" => CONTROL_FLOW_NO_RENDER,
+ "1 render among blocks (1 render, 8 end tags)" => SINGLE_RENDER_AMONG_BLOCKS,
+ "20x block-form renders (20 renders, 20 end tags)" => BLOCK_FORM_20X,
+ "1 render among 50 nested blocks (1 render, 51 end tags)" => RENDER_AMONG_50_BLOCKS,
+ "20 renders interleaved with blocks (20 renders, 20 end tags)" => INTERLEAVED_RENDERS_AND_BLOCKS,
}
# -- Benchmark -----------------------------------------------------------------
@@ -44,8 +151,13 @@ Benchmark.ips do |x|
x.config(time: 10, warmup: 5)
TEMPLATES.each do |label, source|
- x.report("parse: #{label}") do
+ begin
Liquid::Template.parse(source, environment: env)
+ x.report("parse: #{label}") do
+ Liquid::Template.parse(source, environment: env)
+ end
+ rescue Liquid::SyntaxError => e
+ puts " Skipping '#{label}' - #{e.message}"
end
end