mirror of
https://github.com/Shopify/liquid.git
synced 2026-10-02 16:45:12 -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))
|
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|
|
Benchmark.ips do |x|
|
||||||
x.report("render") { @template.render(context) }
|
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
|
show_ruby = ENV["SHOW_RUBY"] && ENV["SHOW_RUBY"].to_i || 0
|
||||||
STDERR.puts @ruby if show_ruby >= 1
|
STDERR.puts @ruby if show_ruby >= 1
|
||||||
res = RubyVM::InstructionSequence.compile(<<~RUBY).eval.call(@nodes)
|
res = RubyVM::InstructionSequence.compile(<<~RUBY).eval.call(@nodes)
|
||||||
|
# frozen_string_literal: true
|
||||||
->(__nodes) {
|
->(__nodes) {
|
||||||
->(__context, __output, __l_product) {
|
->(__context, __output, __l_product) {
|
||||||
__scope = __context.environments.first
|
__assigns = __context.scopes.last
|
||||||
#{@ruby}
|
#{@ruby}
|
||||||
__output
|
__output
|
||||||
}
|
}
|
||||||
@@ -60,10 +61,11 @@ module Liquid
|
|||||||
end
|
end
|
||||||
|
|
||||||
def output(node)
|
def output(node)
|
||||||
self << if node.is_a?(String)
|
compiled = compile_expr(node)
|
||||||
"__output << #{node.inspect}\n"
|
self << if compiled.is_a?(String)
|
||||||
|
"__output << #{compiled}\n"
|
||||||
else
|
else
|
||||||
"__output << #{compile_expr(node)}.to_s\n"
|
"__output << #{compiled}.to_s\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -202,7 +204,7 @@ module Liquid
|
|||||||
RUBY
|
RUBY
|
||||||
},
|
},
|
||||||
"escape" => ->(compiler, expr, args, kwargs) {
|
"escape" => ->(compiler, expr, args, kwargs) {
|
||||||
"(_t = #{expr}; CGI.escape(_t) if _t)"
|
"(_t = #{expr}; CGI.escapeHTML(_t) if _t)"
|
||||||
},
|
},
|
||||||
"money" => ->(compiler, expr, args, kwargs) {
|
"money" => ->(compiler, expr, args, kwargs) {
|
||||||
"(_m = #{expr}; _m.nil? ? '' : \"$ \#{(_m / 100.0).round(2)}\")"
|
"(_m = #{expr}; _m.nil? ? '' : \"$ \#{(_m / 100.0).round(2)}\")"
|
||||||
@@ -302,26 +304,26 @@ module Liquid
|
|||||||
|
|
||||||
class Condition
|
class Condition
|
||||||
def compile_expr(compiler)
|
def compile_expr(compiler)
|
||||||
condition = if operator
|
if operator
|
||||||
left_expr = compiler.compile_expr(left)
|
left_expr = compiler.compile_expr(left)
|
||||||
right_expr = compiler.compile_expr(right)
|
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
|
else
|
||||||
left_expr = compiler.compile_expr(left)
|
left_expr = compiler.compile_expr(left)
|
||||||
right_expr = compiler.compile_expr(right)
|
|
||||||
expr = "#{left_expr}"
|
expr = "#{left_expr}"
|
||||||
end
|
end
|
||||||
if child_condition
|
|
||||||
child_expr = compiler.compile_expr(child_condition)
|
|
||||||
condition << " #{child_expr}"
|
|
||||||
end
|
|
||||||
condition
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class Assign
|
class Assign
|
||||||
def compile(compiler)
|
def compile(compiler)
|
||||||
compliler.declare(@to)
|
compiler.declare(compiler.var_name(@to))
|
||||||
compiler << "#{compiler.var_name(@to)} = #{compiler.compile_expr(@from)}\n"
|
compiler << "#{compiler.var_name(@to)} = #{compiler.compile_expr(@from)}\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user