| Commit message (Collapse) | Author | Age | Files | Lines |
... | |
| |
|
|
|
|
|
|
| |
we want to try to pull this logic up to where the user actually passed
in "controller" so that it's close to the related call. That way when
we're down the stack, we don't need to wonder "why are we doing this?"
|
| |
|
|
|
|
|
| |
There are some cases where :path is nil on option and we should respect
that.
|
|
|
|
| |
We already know how to handle `path`, so lets just handle it on our own.
|
|
|
|
|
|
|
| |
All callers of `action_path` interpolate the return value in to a
string, so there is no need for the method to to_s it. to_sym on a
symbol will return the same symbol, though I think `action_path` may
always be called with a symbol so this might not be necessary.
|
|
|
|
| |
we only need to check for `path` once.
|
|
|
|
| |
Now we can see where `defaults` options originate
|
| |
|
|
|
|
|
| |
since `controller` and `controller_scope` were the same, just combine
them
|
| |
|
|
|
|
|
| |
This method isn't used internally, isn't tested, isn't documented. We
should delete it.
|
|
|
|
|
| |
add a predicate method so that we can avoid is_a? calls on the resource
object.
|
|
|
|
|
| |
calling `scope` isn't cheap, so try to call cheaper methods that do the
same thing for those particular parameters (in this case `path_scope`)
|
|
|
|
|
| |
`resource_scope` should just put resource scopes on the stack, and
doesn't need to know what a `scope_level` is.
|
|
|
|
|
| |
We just want to augment the scope level, not the frame itself, so just
copy the frame to the new scope object.
|
|
|
|
| |
this gives us an easier way to iterate the stack
|
|
|
|
|
| |
The same information is stored in the `@scope` linked list, so just get
it from there.
|
|
|
|
| |
this lets us remove the setter and make the Resource object Read-Only
|
|
|
|
|
| |
We don't need to ask `scope` for the resource because we already have it
right here.
|
|
|
|
|
| |
This method raises conditionally not always so we should not documment
as it always raise.
|
| |
|
|
|
|
|
| |
We should return when the contoller key is not present or if the
controller doesn't exist and we didn't raised an error.
|
|
|
|
| |
Related with dc1b937db780155089fce522f03d340e62f5df36
|
|
|
|
|
|
| |
eliminates calling `scope` in one method, pushes the other calls up one
frame. This goes a little way towards eliminating the internal calls to
`scope`.
|
|
|
|
| |
we don't really need this hash.
|
|
|
|
|
|
|
| |
we need to get a grip on what `scope` actually does. This commit
removes some of the internal calls to `scope`. Eventually we should add
public facing methods that provide the API that `scope` is trying to
accomplish.
|
|
|
|
|
|
| |
`prepare_params!` would raise an exception if `params` wasn't
initialized, so it must always be available. Remove the existence
conditional from the `controller` method.
|
|
|
|
|
| |
The method we called already has the conditional we need. Just add an
else block so that we don't need two tests.
|
|
|
|
|
|
|
| |
`Dispatcher` doesn't need to hold on to the defaults hash. It only used
the hash to determine whether or not it should raise an exception if
there is a name error. We can pass that in further up the stack and
alleviate Dispatcher from knowing about that hash.
|
|
|
|
|
|
| |
We know in advance whether the object is a dispatcher or not, so we can
configure the Constraints object with a strategy that will call the
right method.
|
| |
|
|
|
|
| |
it isn't used.
|
|\
| |
| | |
replace each with each_key when only the key is needed
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
Using each_key is faster and more intention revealing.
Calculating -------------------------------------
each 31.378k i/100ms
each_key 33.790k i/100ms
-------------------------------------------------
each 450.225k (± 7.0%) i/s - 2.259M
each_key 494.459k (± 6.3%) i/s - 2.467M
Comparison:
each_key: 494459.4 i/s
each: 450225.1 i/s - 1.10x slower
|
| | |
|
| |
| |
| |
| | |
scope so that they are available to subclasses.
|
|/ |
|
|\
| |
| | |
Remove duplicated `Array#to_param`
|
| |
| |
| |
| |
| | |
`Array#to_param` is defind in active_support/core_ext/object/to_query.rb,
so we can call `to_param` if value is_a Array.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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.
|
| |
| |
| |
| |
| |
| | |
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).
|
| |
| |
| |
| |
| |
| | |
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.
|
| |
| |
| |
| | |
Saves 888 string objects per request.
|
| |
| |
| |
| |
| |
| |
| |
| | |
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.
|
|/
|
|
|
|
|
|
| |
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.
|
|\
| |
| | |
Remove unnecessary `dup` from Mapper `add_route`
|
| |
| |
| |
| |
| |
| |
| | |
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`.
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| | |
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)
|