Alter regexp on initialize to avoid extra ast pass

Along the same lines as #38901, #39903, and #39914, this commit removes
one pass through the journey ast in an attempt to improve application
boot time.

Before this commit, `Mapper#path` would iterate through the ast to alter
the regex for custom routes. With this commit we move the regex
alterations to initialize, where we were already iterating through the
ast.

The Benchmark for this change is similar to what we have been seeing in
the other PRs.

```
Warming up --------------------------------------
               after    13.121k i/100ms
              before     7.416k i/100ms
Calculating -------------------------------------
               after    128.469k (± 3.1%) i/s -    642.929k in 5.009391s
              before     76.561k (± 1.8%) i/s -    385.632k in 5.038677s

Comparison:
               after:   128469.4 i/s
              before:    76560.8 i/s - 1.68x  (± 0.00) slower

Calculating -------------------------------------
               after   160.000  memsize (     0.000  retained)
                         3.000  objects (     0.000  retained)
                         0.000  strings (     0.000  retained)
              before   360.000  memsize (     0.000  retained)
                         6.000  objects (     0.000  retained)
                         0.000  strings (     0.000  retained)

Comparison:
               after:        160 allocated
              before:        360 allocated - 2.25x more
```
上级 f0de4734
......@@ -137,6 +137,8 @@ def initialize(set:, ast:, controller:, default_action:, to:, formatted:, via:,
# Add a constraint for wildcard route to make it non-greedy and match the
# optional format part of the route by default.
wildcard_options[node.name.to_sym] ||= /.+?/
elsif node.cat?
alter_regex_for_custom_routes(node)
end
end
......@@ -185,8 +187,10 @@ def application
app(@blocks)
end
JOINED_SEPARATORS = SEPARATORS.join # :nodoc:
def path
build_path @ast, requirements, @anchor
Journey::Path::Pattern.new(@ast, requirements, JOINED_SEPARATORS, @anchor)
end
def conditions
......@@ -207,16 +211,10 @@ def request_method
end
private :request_method
JOINED_SEPARATORS = SEPARATORS.join # :nodoc:
def build_path(ast, requirements, anchor)
pattern = Journey::Path::Pattern.new(ast, requirements, JOINED_SEPARATORS, anchor)
private
# Find all the symbol nodes that are adjacent to literal nodes and alter
# the regexp so that Journey will partition them into custom routes.
ast.find_all { |node|
next unless node.cat?
def alter_regex_for_custom_routes(node)
if node.left.literal? && node.right.symbol?
symbol = node.right
elsif node.left.literal? && node.right.cat? && node.right.left.symbol?
......@@ -225,20 +223,13 @@ def build_path(ast, requirements, anchor)
symbol = node.left
elsif node.left.symbol? && node.right.cat? && node.right.left.literal?
symbol = node.left
else
next
end
if symbol
symbol.regexp = /(?:#{Regexp.union(symbol.regexp, '-')})+/
end
}
pattern
end
private :build_path
end
private
def intern(object)
object.is_a?(String) ? -object : object
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册