Compare commits

...

3 Commits

Author SHA1 Message Date
Marc-André Cournoyer
9cc410478e Refactor the Optimizer class no visit the AST
Just takes care of Variables for now.

Increases performance.
2020-10-07 16:06:50 -04:00
Marc-André Cournoyer
4196a94aa3 Plug Optimizer in Document.parse 2020-10-07 13:47:48 -04:00
Marc-André Cournoyer
0de722968c Introduce the AST Optimizer
... that can only optimize one thing: combine `| append: 'a' | append: 'b'` into a single `| append_all: ['a', 'b']` filter call.

This avoids all the intermediate allocations caused by several `append`.

Also introduce a new filter `append_all: [*items]`.
2020-10-07 13:47:42 -04:00
5 changed files with 42 additions and 0 deletions

View File

@@ -84,6 +84,7 @@ require 'liquid/usage'
require 'liquid/register'
require 'liquid/static_registers'
require 'liquid/template_factory'
require 'liquid/optimizer'
# Load all the tags of the standard library
#

19
lib/liquid/optimizer.rb Normal file
View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
module Liquid
class Optimizer
class << self
attr_accessor :enabled
def optimize_variable(node)
return unless enabled
# Turn chained `| append: "..."| append: "..."`, into a single `append_all: [...]`
if node.filters.size > 1 && node.filters.all? { |f, _| f == "append" }
node.filters = [["append_all", node.filters.map { |f, (arg)| arg }]]
end
end
end
self.enabled = true
end
end

View File

@@ -281,6 +281,10 @@ module Liquid
input.to_s + string.to_s
end
def append_all(input, *items)
input.to_s + items.join
end
def concat(input, array)
unless array.respond_to?(:to_ary)
raise ArgumentError, "concat filter requires an array argument"

View File

@@ -31,6 +31,8 @@ module Liquid
@line_number = parse_context.line_number
parse_with_selected_parser(markup)
Optimizer.optimize_variable(self)
end
def raw

View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true
require 'test_helper'
class OptimizerUnitTest < Minitest::Test
include Liquid
def test_combines_append_filters
optimizer = Optimizer.new
var = Variable.new('hello | append: "a" | append: b', ParseContext.new)
var = optimizer.optimize(var)
assert_equal([
['append_all', ["a", VariableLookup.new("b")]]
], var.filters)
end
end