aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_dispatch
Commit message (Collapse)AuthorAgeFilesLines
...
* | | move env access to the request object.Aaron Patterson2015-08-052-14/+46
| | | | | | | | | | | | | | | | | | Accessing a request object has nice advantages over accessing a hash. If you use a missing method name, you'll get an exception rather than a `nil` (is one nice feature)
* | | routes in the env via the request objectAaron Patterson2015-08-051-0/+4
| | |
* | | allocate a request object to avoid hash allocationsAaron Patterson2015-08-051-0/+4
|/ / | | | | | | | | This decouples the `call` method from knowing the SCRIPT_NAME key and offloads decisions about how to access script_name
* | Use #start_with? and #[] for speedBenjamin Quorning2015-08-021-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | While the readability may be slightly worse, the speed improvement is significant: Twice as fast when there's no leading "/" to remove, and over 4 times as fast when there is a leading "/". Benchmark: require 'benchmark/ips' def match(controller) if controller if m = controller.match(/\A\/(?<controller_without_leading_slash>.*)/) m[:controller_without_leading_slash] else controller end end end def start_with(controller) if controller if controller.start_with?('/'.freeze) controller[1..-1] else controller end end end Benchmark.ips do |x| x.report("match") { match("no_leading_slash") } x.report("start_with") { start_with("no_leading_slash") } x.compare! end Benchmark.ips do |x| x.report("match") { match("/a_leading_slash") } x.report("start_with") { start_with("/a_leading_slash") } x.compare! end Result (Ruby 2.2.2): Calculating ------------------------------------- match 70.324k i/100ms start_with 111.264k i/100ms ------------------------------------------------- match 1.468M (± 7.1%) i/s - 7.314M start_with 3.787M (± 3.5%) i/s - 18.915M Comparison: start_with: 3787389.4 i/s match: 1467636.4 i/s - 2.58x slower Calculating ------------------------------------- match 36.694k i/100ms start_with 86.071k i/100ms ------------------------------------------------- match 532.795k (± 4.7%) i/s - 2.679M start_with 2.518M (± 5.8%) i/s - 12.566M Comparison: start_with: 2518366.8 i/s match: 532794.5 i/s - 4.73x slower
* | [ci skip]yui-knk2015-08-011-0/+15
| | | | | | | | | | | | | | | | | | | | | | Add descriptions about `ActiveRecord::Base#to_param` to * `ActionDispatch::Routing::Base#match` * Overriding Named Route Parameters (guide) When passes `:param` to route definision, always `to_param` method of related model is overridden to constructe an URL by passing these model instance to named_helper.
* | Array#any? is slower and not the inverse of Array#empty?Jean Boussier2015-07-301-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ``` empty_array = [] small_array = [1] * 30 bigger_array = [1] * 300 Benchmark.ips do |x| x.report('empty !empty?') { !empty_array.empty? } x.report('small !empty?') { !small_array.empty? } x.report('bigger !empty?') { !bigger_array.empty? } x.report('empty any?') { empty_array.any? } x.report('small any?') { small_array.any? } x.report('bigger any?') { bigger_array.any? } end ``` ``` Calculating ------------------------------------- empty !empty? 132.059k i/100ms small !empty? 133.974k i/100ms bigger !empty? 133.848k i/100ms empty any? 106.924k i/100ms small any? 85.525k i/100ms bigger any? 86.663k i/100ms ------------------------------------------------- empty !empty? 8.522M (± 7.9%) i/s - 42.391M small !empty? 8.501M (± 8.5%) i/s - 42.202M bigger !empty? 8.434M (± 8.6%) i/s - 41.894M empty any? 4.161M (± 8.3%) i/s - 20.743M small any? 2.654M (± 5.2%) i/s - 13.256M bigger any? 2.642M (± 6.4%) i/s - 13.173M ``` Ref: https://github.com/rails/rails/pull/21057#discussion_r35902468
* | Use delete_if instead of each; delete(key)schneems2015-07-301-3/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | It is slightly faster: ``` Calculating ------------------------------------- each; delete 35.166k i/100ms delete_if 36.416k i/100ms ------------------------------------------------- each; delete 478.026k (± 8.5%) i/s - 2.391M delete_if 485.123k (± 7.9%) i/s - 2.440M ```
* | Remove (another) array allocationschneems2015-07-301-5/+14
| | | | | | | | | | | | We don't always need an array when generating a url with the formatter. We can be lazy about allocating the `missing_keys` array. This saves us: 35,606 bytes and 889 objects per request
* | Remove array allocationschneems2015-07-301-2/+2
| | | | | | | | | | | | THe only reason we were allocating an array is to get the "missing_keys" variable in scope of the error message generator. Guess what? Arrays kinda take up a lot of memory, so by replacing that with a nil, we save: 35,303 bytes and 886 objects per request
* | Avoid hash duplication by skipping mutationschneems2015-07-301-2/+2
| | | | | | | | | | | | If we don't mutate the `recall` hash, then there's no reason to duplicate it. While this change doesn't get rid of that many objects, each hash object it gets rid of was massive. Saves 888 string objects per request, 206,013 bytes (thats 0.2 mb which is kinda a lot).
* | Only allocate new string when neededschneems2015-07-301-1/+7
| | | | | | | | | | | | Instead of calling `sub` on every link_to call for controller, we can detect when the string __needs__ to be allocated and only then create a new string (without the leading slash), otherwise, use the string that is given to us. Saves 888 string objects per request, 35,524 bytes.
* | Freeze a string in comparatorschneems2015-07-301-1/+1
| | | | | | | | Saves 888 string objects per request.
* | Avoid calling to_s on nil in journey/formatterschneems2015-07-301-2/+2
| | | | | | | | | | | | | | | | When `defaults[key]` in `generate` in the journey formatter is called, it often returns a `nil` when we call `to_s` on a nil, it allocates an empty string. We can skip this check when the default value is nil. This change buys us 35,431 bytes of memory and 887 fewer objects per request. Thanks to @matthewd for help with the readability
* | Reduce hash allocations in route_setschneems2015-07-291-1/+1
| | | | | | | | | | | | | | | | When generating a url with `url_for` the hash of arguments passed in, is dup-d and merged a TON. I wish I could clean this up better, and might be able to do it in the future. This change removes one dup, since it's literally right after we just dup-d the hash to pass into this constructor. This may be a breaking, change but the tests pass...so :shipit: we can revert if it causes problems This change buys us 205,933 bytes of memory and 887 fewer objects per request.
* | Decrease route_set allocationsschneems2015-07-291-3/+7
| | | | | | | | | | | | | | | | In handle_positional_args `Array#-=` is used which allocates a new array. Instead we can iterate through and delete elements, modifying the array in place. Also `Array#take` allocates a new array. We can build the same by iterating over the other element. This change buys us 106,470 bytes of memory and 2,663 fewer objects per request.
* | Speed up journey missing_keysschneems2015-07-291-3/+15
| | | | | | | | | | | | | | | | Most routes have a `route.path.requirements[key]` of `/[-_.a-zA-Z0-9]+\/[-_.a-zA-Z0-9]+/` yet every time this method is called a new regex is generated on the fly with `/\A#{DEFAULT_INPUT}\Z/`. OBJECT ALLOCATIONS BLERG! This change uses a special module that implements `===` so it can be used in a case statement to pull out the default input. When this happens, we use a pre-generated regex. This change buys us 1,643,465 bytes of memory and 7,990 fewer objects per request.
* | Speed up journey extract_parameterized_partsschneems2015-07-291-2/+3
|/ | | | | | | | Micro optimization: `reverse.drop_while` is slower than `reverse_each.drop_while`. This doesn't save any object allocations. Second, `keys_to_keep` is typically a very small array. The operation `parameterized_parts.keys - keys_to_keep` actually allocates two arrays. It is quicker (I benchmarked) to iterate over each and check inclusion in array manually. This change buys us 1774 fewer objects per request
* Tiny documentation edits [ci skip]Robin Dupret2015-07-281-1/+1
|
* Add `:nodoc:` for internal testing methods [ci skip]Robin Dupret2015-07-281-1/+1
|
* Merge pull request #20590 from vngrs/set_default_charsetRafael Mendonça França2015-07-271-6/+6
|\ | | | | Document, refactor and create test case for ActionDispatch::Response
| * Document, refactor and create test case for ↵Mehmet Emin İNAÇ2015-06-171-6/+6
| | | | | | | | ActionDispatch::Response#charset= method
* | rm `deep_munge`. You will live on in our hearts (and git history)Aaron Patterson2015-07-213-26/+15
| | | | | | | | | | Now that we have encoding strategies, we can just walk the params hash once to encode as HWIA, and remove nils.
* | push param encoding in to the utils moduleAaron Patterson2015-07-212-14/+30
| | | | | | | | we'll refactor deep munge mostly out of existence shortly
* | stop keeping track of keys when "deep munging"Aaron Patterson2015-07-211-5/+3
| | | | | | | | This should have been done along with 8f8ccb9901cab457c6e1d52bdb25acf658fd5777
* | recurse for arrays in `normalize_encode_params`Aaron Patterson2015-07-211-5/+3
| | | | | | | | | | this just pushes the conditional in to the case / when so we can switch to method dispatch later
* | Merge pull request #20751 from repinel/remove-unnecessary-dupRafael Mendonça França2015-07-201-1/+1
|\ \ | | | | | | Remove unnecessary `dup` from Mapper `add_route`
| * | Remove unnecessary `dup` from Mapper `add_route`Roque Pinel2015-07-011-1/+1
| | | | | | | | | | | | | | | | | | | | | The `dup` was introduced by c4106d0c08954b0761726e0015ec601b7bc7ea4b to work around a frozen key. Nowadays, the string is already being duplicated by the `tr` in `options[:action] ||= action.tr('-', '_')` and later joined into a new string in `name_for_action`.
* | | Freeze string literals when not mutated.schneems2015-07-196-13/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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)
* | | Stop using deprecated `render :text` in testPrem Sichanugrist2015-07-171-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | This will silence deprecation warnings. Most of the test can be changed from `render :text` to render `:plain` or `render :body` right away. However, there are some tests that needed to be fixed by hand as they actually assert the default Content-Type returned from `render :body`.
* | | Oops! :bomb:Akira Matsuda2015-07-171-1/+1
| | |
* | | "warning: instance variable @routes not initialized"Akira Matsuda2015-07-171-1/+1
| | |
* | | Make AC::Parameters not inherited from HashPrem Sichanugrist2015-07-151-0/+4
| | | | | | | | | | | | | | | | | | | | | | | | This is another take at #14384 as we decided to wait until `master` is targeting Rails 5.0. This commit is implementation-complete, as it guarantees that all the public methods on the hash-inherited Parameters are still working (based on test case). We can decide to follow-up later if we want to remove some methods out from Parameters.
* | | Rack implements `redirect?` so we don't need itAaron Patterson2015-07-141-3/+0
| | | | | | | | | | | | Rack [already implements `redirect?` on the response object](https://github.com/rack/rack/blob/1569a985e17d9caaf94d0e97d95ef642c4ab14ba/lib/rack/response.rb#L141) so we don't need to implement our own.
* | | use a lookup table for `assert_response`Aaron Patterson2015-07-131-3/+8
| | | | | | | | | | | | | | | | | | | | | | | | We shouldn't depend on specific methods imlemented in the TestResponse subclass because the response could actually be a real response object. In the future, we should either push the aliased predicate methods in TestResponse up to the real response object, or remove them
* | | move buffer caching on to the bufferAaron Patterson2015-07-131-3/+11
| | |
* | | Merge pull request #20842 from TheBlasfem/removed_usage_lines_docsClaudio B.2015-07-111-1/+1
|\ \ \ | | | | | | | | Removed usage line docs [ci skip]
| * | | added description instead of remove usage [ci skip]Julio Lopez2015-07-111-1/+1
| | | |
* | | | Merge pull request #17102 from matthewd/load-interlockAaron Patterson2015-07-101-0/+21
|\ \ \ \ | | | | | | | | | | Concurrent load interlock (rm Rack::Lock)
| * | | | Fix the Interlock middlewareMatthew Draper2015-07-091-5/+14
| | | | | | | | | | | | | | | | | | | | | | | | | We can't actually lean on Rack::Lock's implementation, so we'll just copy it instead. It's simple enough that that's not too troubling.
| * | | | Soften the lock requirements when eager_load is disabledMatthew Draper2015-07-091-0/+12
| | | | | | | | | | | | | | | | | | | | | | | | | We don't need to fully disable concurrent requests: just ensure that loads are performed in isolation.
* | | | | start disconnecting the parameter parser from the instanceAaron Patterson2015-07-101-3/+3
| | | | | | | | | | | | | | | | | | | | | | | | | pass in the instance variable to start decoupling the meat of the parser from the instance of the middleware
* | | | | drop a conditional by always assigningAaron Patterson2015-07-101-6/+5
| |/ / / |/| | | | | | | | | | | | | | | We will always make an assignment to the env hash and eliminate a conditional
* | | | drop runtime conditionals in parameter parsingAaron Patterson2015-07-091-13/+9
| | | | | | | | | | | | | | | | | | | | If we only deal with proc objects, then we can eliminate type checking in the parameter parsing middleware
* | | | assign the cookie hash on request allocationAaron Patterson2015-07-081-1/+1
| | | | | | | | | | | | | | | | this prevents mutations from being available globally
* | | | add a new constructor for allocating test requestsAaron Patterson2015-07-082-9/+9
| | | |
* | | | make `env` a required parameterAaron Patterson2015-07-081-1/+1
| | | |
* | | | pass the starting env and session to build_requestAaron Patterson2015-07-081-1/+1
| | | |
* | | | let the superclass build the request and responseAaron Patterson2015-07-081-1/+1
| | | | | | | | | | | | | | | | | | | | We should leverage the request / response objects that the superclass has already allocated for us.
* | | | remove useless `new` implementationAaron Patterson2015-07-081-4/+0
|/ / /
* | | pass cookies from the jar in the HTTP_COOKIE headereileencodes2015-07-071-9/+4
| | | | | | | | | | | | | | | we should be pushing the cookies in via headers rather than maintaining some object and "recycling" it.