Lazy Context init: defer StringScanner and @interrupts array allocation until needed\n\nResult: {"status":"keep","combined_µs":4299,"parse_µs":3057,"render_µs":1242,"allocations":26015}

This commit is contained in:
Tobi Lutke
2026-04-04 17:42:33 -07:00
committed by Chris Pak
parent 02764d28f7
commit 1800cffd3b
+6 -6
View File
@@ -38,14 +38,13 @@ module Liquid
@strict_variables = false @strict_variables = false
@resource_limits = resource_limits || ResourceLimits.new(environment.default_resource_limits) @resource_limits = resource_limits || ResourceLimits.new(environment.default_resource_limits)
@base_scope_depth = 0 @base_scope_depth = 0
@interrupts = [] @interrupts = Const::EMPTY_ARRAY
@filters = Const::EMPTY_ARRAY @filters = Const::EMPTY_ARRAY
@global_filter = nil @global_filter = nil
@disabled_tags = Const::EMPTY_HASH @disabled_tags = Const::EMPTY_HASH
# Instead of constructing new StringScanner objects for each Expression parse, # Lazy-init StringScanner — only needed if Context#[] is called during render
# we recycle the same one. @string_scanner = nil
@string_scanner = StringScanner.new("")
@registers.static[:cached_partials] ||= {} @registers.static[:cached_partials] ||= {}
@registers.static[:file_system] ||= environment.file_system @registers.static[:file_system] ||= environment.file_system
@@ -87,11 +86,12 @@ module Liquid
# are there any not handled interrupts? # are there any not handled interrupts?
def interrupt? def interrupt?
!@interrupts.empty? !@interrupts.frozen? && !@interrupts.empty?
end end
# push an interrupt to the stack. this interrupt is considered not handled. # push an interrupt to the stack. this interrupt is considered not handled.
def push_interrupt(e) def push_interrupt(e)
@interrupts = [] if @interrupts.frozen?
@interrupts.push(e) @interrupts.push(e)
end end
@@ -194,7 +194,7 @@ module Liquid
# Example: # Example:
# products == empty #=> products.empty? # products == empty #=> products.empty?
def [](expression) def [](expression)
evaluate(Expression.parse(expression, @string_scanner)) evaluate(Expression.parse(expression, @string_scanner ||= StringScanner.new("")))
end end
def key?(key) def key?(key)