1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Optimize Journey::Route#score

Scoring routes based on constraints repeated many type conversions that
could be performed in the outer loop.  Determinations of score and
fitness also used Array operations that required allocations.  Against
my benchmark with a large routeset, this reduced object allocations by
over 30x and wall time by over 3x.
This commit is contained in:
Ben Hughes 2016-12-28 11:35:43 -08:00
parent 47cda2e1f6
commit f1525dac11
3 changed files with 15 additions and 6 deletions

View file

@ -92,7 +92,11 @@ module ActionDispatch
else
routes = non_recursive(cache, options)
hash = routes.group_by { |_, r| r.score(options) }
supplied_keys = options.each_with_object({}) do |(k, v), h|
h[k.to_s] = true if v
end
hash = routes.group_by { |_, r| r.score(supplied_keys) }
hash.keys.sort.reverse_each do |score|
break if score < 0

View file

@ -96,13 +96,18 @@ module ActionDispatch
required_parts + required_defaults.keys
end
def score(constraints)
def score(supplied_keys)
required_keys = path.required_names
supplied_keys = constraints.map { |k, v| v && k.to_s }.compact
return -1 unless (required_keys - supplied_keys).empty?
required_keys.each do |k|
return -1 unless supplied_keys.include?(k)
end
score = 0
path.names.each do |k|
score += 1 if supplied_keys.include?(k)
end
score = (supplied_keys & path.names).length
score + (required_defaults.length * 2)
end

View file

@ -96,7 +96,7 @@ module ActionDispatch
path = Path::Pattern.from_string "/:controller(/:action(/:id))(.:format)"
generic = Route.build "name", nil, path, constraints, [], {}
knowledge = { id: 20, controller: "pages", action: "show" }
knowledge = { "id" => true, "controller" => true, "action" => true }
routes = [specific, generic]