# frozen_string_literal: true require "benchmark/ips" # Benchmark hybrid render tag parsing overhead. require 'liquid' RubyVM::YJIT.enable if defined?(RubyVM::YJIT) # -- Templates ----------------------------------------------------------------- SINGLE_SELF_CLOSING = "{% render 'snippet' %}" MULTIPLE_SELF_CLOSING = (1..20).map { |i| "{% render 'snippet_#{i}' %}" }.join("\n") 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' %} {% for item in collection %} {% render 'card' %}

{{ item.title }}

{% endfor %} {% render 'footer' %} 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 ----------------------------------------------------------------- env = Liquid::Environment.default Benchmark.ips do |x| x.config(time: 10, warmup: 5) TEMPLATES.each do |label, source| 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 x.compare! end