mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-17 18:00:41 -07:00
Perf: Remove unneeded to_s and freeze strings
- No longer call to_s on string literals passed to undefined filters - Freeze all string literals at the top of the generated code This shows a ~9% performance improvement on the fluid benchmark when run without YJIT
This commit is contained in:
@@ -18,14 +18,6 @@ Liquid::Template.register_filter(ShopFilter)
|
||||
|
||||
context = Liquid::Context.new([tables, {}], {}, {}, false, Liquid::ResourceLimits.new(Liquid::Template.default_resource_limits))
|
||||
|
||||
require 'stackprof'
|
||||
|
||||
results = StackProf.run(raw: true, out: 'stackprof.dump') do
|
||||
500_000.times do
|
||||
@template.render(context)
|
||||
end
|
||||
end
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report("render") { @template.render(context) }
|
||||
|
||||
|
||||
+16
-14
@@ -31,9 +31,10 @@ module Liquid
|
||||
show_ruby = ENV["SHOW_RUBY"] && ENV["SHOW_RUBY"].to_i || 0
|
||||
STDERR.puts @ruby if show_ruby >= 1
|
||||
res = RubyVM::InstructionSequence.compile(<<~RUBY).eval.call(@nodes)
|
||||
# frozen_string_literal: true
|
||||
->(__nodes) {
|
||||
->(__context, __output, __l_product) {
|
||||
__scope = __context.environments.first
|
||||
__assigns = __context.scopes.last
|
||||
#{@ruby}
|
||||
__output
|
||||
}
|
||||
@@ -60,10 +61,11 @@ module Liquid
|
||||
end
|
||||
|
||||
def output(node)
|
||||
self << if node.is_a?(String)
|
||||
"__output << #{node.inspect}\n"
|
||||
compiled = compile_expr(node)
|
||||
self << if compiled.is_a?(String)
|
||||
"__output << #{compiled}\n"
|
||||
else
|
||||
"__output << #{compile_expr(node)}.to_s\n"
|
||||
"__output << #{compiled}.to_s\n"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -202,7 +204,7 @@ module Liquid
|
||||
RUBY
|
||||
},
|
||||
"escape" => ->(compiler, expr, args, kwargs) {
|
||||
"(_t = #{expr}; CGI.escape(_t) if _t)"
|
||||
"(_t = #{expr}; CGI.escapeHTML(_t) if _t)"
|
||||
},
|
||||
"money" => ->(compiler, expr, args, kwargs) {
|
||||
"(_m = #{expr}; _m.nil? ? '' : \"$ \#{(_m / 100.0).round(2)}\")"
|
||||
@@ -302,26 +304,26 @@ module Liquid
|
||||
|
||||
class Condition
|
||||
def compile_expr(compiler)
|
||||
condition = if operator
|
||||
if operator
|
||||
left_expr = compiler.compile_expr(left)
|
||||
right_expr = compiler.compile_expr(right)
|
||||
expr = "((#{left_expr} #{operator} #{right_expr}) #{child_relation}"
|
||||
if child_relation
|
||||
child_expr = compiler.compile_expr(child_condition)
|
||||
expr = "((#{left_expr} #{operator} #{right_expr}) #{child_relation} #{child_expr})"
|
||||
else
|
||||
expr = "(#{left_expr} #{operator} #{right_expr})"
|
||||
end
|
||||
expr
|
||||
else
|
||||
left_expr = compiler.compile_expr(left)
|
||||
right_expr = compiler.compile_expr(right)
|
||||
expr = "#{left_expr}"
|
||||
end
|
||||
if child_condition
|
||||
child_expr = compiler.compile_expr(child_condition)
|
||||
condition << " #{child_expr}"
|
||||
end
|
||||
condition
|
||||
end
|
||||
end
|
||||
|
||||
class Assign
|
||||
def compile(compiler)
|
||||
compliler.declare(@to)
|
||||
compiler.declare(compiler.var_name(@to))
|
||||
compiler << "#{compiler.var_name(@to)} = #{compiler.compile_expr(@from)}\n"
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user