aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch/journey/nodes
Commit message (Collapse)AuthorAgeFilesLines
* Expand metaprogramming for Symbol, Slash and Dot.Alberto Almagro2018-12-071-6/+7
| | | | | | | | | | | | | | This first started with moving type method inside `ActionDispatch::Journey::Nodes::Symbol`. `AD::Journey::Nodes::Symbol#type` was generated dynamically with an `each` block. While this is OK for classes like `AD::Journey::Nodes::Slash` or `AD::Journey::Nodes::Dot` which don't have further implementation, all other classes containing more logic have this method defined in their class body. This patch does the same in this case. On code review process @kamipo suggested to fully expand over metaprogramming for Slash and Dot classes, a topic on which I agree with him.
* Write the code in a more natural way.Rafael Mendonça França2018-02-161-2/+2
|
* PERF: reduce retained objects in JourneySam2018-02-161-2/+2
| | | | | | | | | | | | | | | | | | | | Before: Total allocated: 209050523 bytes (2219202 objects) Total retained: 36580305 bytes (323462 objects) After: Total allocated: 209180253 bytes (2222455 objects) Total retained: 36515599 bytes (321850 objects) --- Modest saving of 1612 RVALUEs in the heap on Discourse boot The larger the route file the better the results. Saving will only be visible on Ruby 2.5 and up.
* [Action Pack] require => require_relativeAkira Matsuda2017-10-211-1/+1
| | | | | This basically reverts e9fca7668b9eba82bcc832cb0061459703368397, d08da958b9ae17d4bbe4c9d7db497ece2450db5f, d1fe1dcf8ab1c0210a37c2a78c1ee52cf199a66d, and 68eaf7b4d5f2bb56d939f71c5ece2d61cf6680a3
* Use frozen string literal in actionpack/Kir Shatrov2017-07-291-0/+2
|
* [Action Dispatch] require => require_relativeAkira Matsuda2017-07-011-1/+1
|
* applies new string literal convention in actionpack/libXavier Noria2016-08-061-5/+5
| | | | | The current code base is not uniform. After some discussion, we have chosen to go with double quotes by default.
* used predicate methods to avoid is_a? checksRonak Jangir2015-10-101-0/+2
|
* drop array allocations when building pathsAaron Patterson2015-08-181-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ```ruby require 'action_pack' require 'action_dispatch' require 'benchmark/ips' route_set = ActionDispatch::Routing::RouteSet.new routes = ActionDispatch::Routing::Mapper.new route_set ObjectSpace::AllocationTracer.setup(%i{path line type}) result = ObjectSpace::AllocationTracer.trace do 500.times do routes.resources :foo end end sorted = ObjectSpace::AllocationTracer.allocated_count_table.sort_by(&:last) sorted.each do |k,v| next if v == 0 p k => v end __END__ Before: {:T_SYMBOL=>11} {:T_REGEXP=>17} {:T_STRUCT=>6500} {:T_MATCH=>12004} {:T_OBJECT=>99009} {:T_DATA=>100088} {:T_HASH=>122015} {:T_STRING=>159637} {:T_IMEMO=>363134} {:T_ARRAY=>433056} After: {:T_SYMBOL=>11} {:T_REGEXP=>17} {:T_STRUCT=>6500} {:T_MATCH=>12004} {:T_OBJECT=>91009} {:T_DATA=>100088} {:T_HASH=>114013} {:T_STRING=>159637} {:T_ARRAY=>321056} {:T_IMEMO=>351133} ```
* drop string allocations for each resourceAaron Patterson2015-08-181-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Eagerly calculate and cache the name of Symbol objects in the path AST. This drops about 26 string allocations per resource: ```ruby require 'action_pack' require 'action_dispatch' require 'benchmark/ips' route_set = ActionDispatch::Routing::RouteSet.new routes = ActionDispatch::Routing::Mapper.new route_set ObjectSpace::AllocationTracer.setup(%i{path line type}) result = ObjectSpace::AllocationTracer.trace do 500.times do routes.resources :foo end end sorted = ObjectSpace::AllocationTracer.allocated_count_table.sort_by(&:last) sorted.each do |k,v| next if v == 0 p k => v end __END__ Before: {:T_SYMBOL=>11} {:T_REGEXP=>17} {:T_STRUCT=>6500} {:T_MATCH=>12004} {:T_OBJECT=>99009} {:T_DATA=>116084} {:T_HASH=>122015} {:T_STRING=>172647} {:T_IMEMO=>371132} {:T_ARRAY=>433056} After: {:T_SYMBOL=>11} {:T_REGEXP=>17} {:T_STRUCT=>6500} {:T_MATCH=>12004} {:T_OBJECT=>99009} {:T_DATA=>100088} {:T_HASH=>122015} {:T_STRING=>159637} {:T_IMEMO=>363134} {:T_ARRAY=>433056} ```
* drop object allocation during routes setupAaron Patterson2015-08-171-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit introduces a functional Path AST visitor and implements `each` on the AST in terms of the functional visitor. The functional visitor doesn't maintain state, so we only need to allocate one of them. Given this benchmark route file: ```ruby require 'action_pack' require 'action_dispatch' route_set = ActionDispatch::Routing::RouteSet.new routes = ActionDispatch::Routing::Mapper.new route_set ObjectSpace::AllocationTracer.setup(%i{path line type}) result = ObjectSpace::AllocationTracer.trace do 500.times{|i| routes.resource :omglol } end result.find_all { |k,v| k.first =~ /git\/rails/ }.sort_by { |k,v| v.first }.each { |k,v| p k => v } ``` node.rb line 17 was in our top 3 allocation spot: ``` {["/Users/aaron/git/rails/actionpack/lib/action_dispatch/journey/nodes/node.rb", 17, :T_OBJECT]=>[31526, 0, 28329, 0, 2, 1123160]} {["/Users/aaron/git/rails/actionpack/lib/action_dispatch/routing/mapper.rb", 2080, :T_IMEMO]=>[34002, 0, 30563, 0, 2, 1211480]} {["/Users/aaron/git/rails/actionpack/lib/action_dispatch/routing/mapper.rb", 2071, :T_IMEMO]=>[121934, 1, 109608, 0, 7, 4344400]} ``` This commit eliminates allocations at that place.
* avoid is_a? checksAaron Patterson2015-08-171-0/+2
| | | | add another predicate method so we can avoid is_a checks
* use predicate methods to avoid is_a? checksAaron Patterson2015-08-171-0/+2
| | | | | we may want to change the name of the class at some point, so it's better to use a predicate
* Freeze string literals when not mutated.schneems2015-07-191-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I wrote a utility that helps find areas where you could optimize your program using a frozen string instead of a string literal, it's called [let_it_go](https://github.com/schneems/let_it_go). After going through the output and adding `.freeze` I was able to eliminate the creation of 1,114 string objects on EVERY request to [codetriage](codetriage.com). How does this impact execution? To look at memory: ```ruby require 'get_process_mem' mem = GetProcessMem.new GC.start GC.disable 1_114.times { " " } before = mem.mb after = mem.mb GC.enable puts "Diff: #{after - before} mb" ``` Creating 1,114 string objects results in `Diff: 0.03125 mb` of RAM allocated on every request. Or 1mb every 32 requests. To look at raw speed: ```ruby require 'benchmark/ips' number_of_objects_reduced = 1_114 Benchmark.ips do |x| x.report("freeze") { number_of_objects_reduced.times { " ".freeze } } x.report("no-freeze") { number_of_objects_reduced.times { " " } } end ``` We get the results ``` Calculating ------------------------------------- freeze 1.428k i/100ms no-freeze 609.000 i/100ms ------------------------------------------------- freeze 14.363k (± 8.5%) i/s - 71.400k no-freeze 6.084k (± 8.1%) i/s - 30.450k ``` Now we can do some maths: ```ruby ips = 6_226k # iterations / 1 second call_time_before = 1.0 / ips # seconds per iteration ips = 15_254 # iterations / 1 second call_time_after = 1.0 / ips # seconds per iteration diff = call_time_before - call_time_after number_of_objects_reduced * diff * 100 # => 0.4530373333993266 miliseconds saved per request ``` So we're shaving off 1 second of execution time for every 220 requests. Is this going to be an insane speed boost to any Rails app: nope. Should we merge it: yep. p.s. If you know of a method call that doesn't modify a string input such as [String#gsub](https://github.com/schneems/let_it_go/blob/b0e2da69f0cca87ab581022baa43291cdf48638c/lib/let_it_go/core_ext/string.rb#L37) please [give me a pull request to the appropriate file](https://github.com/schneems/let_it_go/blob/b0e2da69f0cca87ab581022baa43291cdf48638c/lib/let_it_go/core_ext/string.rb#L37), or open an issue in LetItGo so we can track and freeze more strings. Keep those strings Frozen ![](https://www.dropbox.com/s/z4dj9fdsv213r4v/let-it-go.gif?dl=1)
* use a parser to extract the group parts from the pathAaron Patterson2014-05-291-0/+4
|
* update AD::Journey to follow Rails coding conventionsFrancesco Rodriguez2012-12-201-5/+5
|
* :nodoc: Journey because is not part of the public API [ci skip]Francesco Rodriguez2012-12-191-12/+12
|
* Integrate Journey into Action DispatchAndrew White2012-12-191-0/+124
Move the Journey code underneath the ActionDispatch namespace so that we don't pollute the global namespace with names that may be used for models. Fixes rails/journey#49.