diff options
author | Sam <sam.saffron@gmail.com> | 2018-02-15 15:03:20 +1100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-15 15:03:20 +1100 |
commit | 24131d4a6a97621c1021231c650793ce29c4ed99 (patch) | |
tree | 6e4256c57b7a42990f2cb0976794282d00f5dce6 | |
parent | fe6adf43e124f4c9132e5a88a80ebba3f10fd2cb (diff) | |
download | rails-24131d4a6a97621c1021231c650793ce29c4ed99.tar.gz rails-24131d4a6a97621c1021231c650793ce29c4ed99.tar.bz2 rails-24131d4a6a97621c1021231c650793ce29c4ed99.zip |
PERF: dedupe scanned route fragments
Per: https://bugs.ruby-lang.org/issues/13077 String @- will dedupe strings.
This takes advantage of this by deduping route fragments that are full of duplication usually.
For Discourse:
Before:
Total allocated: 207574305 bytes (2214916 objects)
Total retained: 36470010 bytes (322194 objects)
After
Total allocated: 207556847 bytes (2214711 objects)
Total retained: 36327973 bytes (318627 objects) <- object that GC can not collect
So we save 3500 or so RVALUES this way, not the largest saving in the world, but worth it especially for large route files.
-rw-r--r-- | actionpack/lib/action_dispatch/journey/scanner.rb | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/actionpack/lib/action_dispatch/journey/scanner.rb b/actionpack/lib/action_dispatch/journey/scanner.rb index 4ae77903fa..5ed587c1b1 100644 --- a/actionpack/lib/action_dispatch/journey/scanner.rb +++ b/actionpack/lib/action_dispatch/journey/scanner.rb @@ -33,6 +33,13 @@ module ActionDispatch end private + + # takes advantage of String @- deduping capabilities in Ruby 2.5 upwards + # see: https://bugs.ruby-lang.org/issues/13077 + def dedup_scan(regex) + r = @ss.scan(regex) + r ? -r : nil + end def scan case @@ -47,15 +54,15 @@ module ActionDispatch [:OR, "|"] when @ss.skip(/\./) [:DOT, "."] - when text = @ss.scan(/:\w+/) + when text = dedup_scan(/:\w+/) [:SYMBOL, text] - when text = @ss.scan(/\*\w+/) + when text = dedup_scan(/\*\w+/) [:STAR, text] - when text = @ss.scan(/(?:[\w%\-~!$&'*+,;=@]|\\[:()])+/) + when text = dedup_scan(/(?:[\w%\-~!$&'*+,;=@]|\\[:()])+/) text.tr! "\\", "" [:LITERAL, text] # any char - when text = @ss.scan(/./) + when text = dedup_scan(/./) [:LITERAL, text] end end |