diff options
author | Ben Hughes <ben@pixelmachine.org> | 2016-12-28 11:35:43 -0800 |
---|---|---|
committer | Ben Hughes <ben@pixelmachine.org> | 2016-12-28 17:19:15 -0800 |
commit | f1525dac115cea40ec41b4f9e267e011be8da22e (patch) | |
tree | 3e2fb4694230c63bc5cbbbb9ead82c25e1466249 /actionpack/lib/action_dispatch | |
parent | 47cda2e1f655d38a204c4df88d780500c1e99316 (diff) | |
download | rails-f1525dac115cea40ec41b4f9e267e011be8da22e.tar.gz rails-f1525dac115cea40ec41b4f9e267e011be8da22e.tar.bz2 rails-f1525dac115cea40ec41b4f9e267e011be8da22e.zip |
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.
Diffstat (limited to 'actionpack/lib/action_dispatch')
-rw-r--r-- | actionpack/lib/action_dispatch/journey/formatter.rb | 6 | ||||
-rw-r--r-- | actionpack/lib/action_dispatch/journey/route.rb | 13 |
2 files changed, 14 insertions, 5 deletions
diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb index 20ff4441a0..1d239addf8 100644 --- a/actionpack/lib/action_dispatch/journey/formatter.rb +++ b/actionpack/lib/action_dispatch/journey/formatter.rb @@ -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 diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb index 0cc8d83ac8..f2ac4818d8 100644 --- a/actionpack/lib/action_dispatch/journey/route.rb +++ b/actionpack/lib/action_dispatch/journey/route.rb @@ -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 |