New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Beyond Ludicrous Speed #21057
Beyond Ludicrous Speed #21057
Commits on Jul 30, 2015
-
Decrease string allocations on AR#respond_to?
When a symbol is passed in, we call `to_s` on it which allocates a string. The two hardcoded symbols that are used internally are `:to_partial_path` and `:to_model`. This change buys us 71,136 bytes of memory and 1,777 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for f80aa59 - Browse repository at this point
Copy the full SHA f80aa59View commit details -
Decrease string allocations in apply_inflections
In `apply_inflections` a string is down cased and some whitespace stripped in the front (which allocate strings). This would normally be fine, however `uncountables` is a fairly small array (10 elements out of the box) and this method gets called a TON. Instead we can keep an array of valid regexes for each uncountable so we don't have to allocate new strings. This change buys us 325,106 bytes of memory and 3,251 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for 1bf50ba - Browse repository at this point
Copy the full SHA 1bf50baView commit details -
Decrease string allocations in url_options
The request.script_name is dup-d which allocates an extra string. It is most commonly an empty string "". We can save a ton of string allocations by checking first if the string is empty, if so we can use a frozen empty string instead of duplicating an empty string. This change buys us 35,714 bytes of memory and 893 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for 83ee043 - Browse repository at this point
Copy the full SHA 83ee043View commit details -
Speed up journey extract_parameterized_parts
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
Configuration menu - View commit details
-
Copy full SHA for 9b82588 - Browse repository at this point
Copy the full SHA 9b82588View commit details -
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.
Configuration menu - View commit details
-
Copy full SHA for 097ec6f - Browse repository at this point
Copy the full SHA 097ec6fView commit details -
Decrease route_set allocations
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.
Configuration menu - View commit details
-
Copy full SHA for 0cbec58 - Browse repository at this point
Copy the full SHA 0cbec58View commit details -
Reduce hash allocations in route_set
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 we can revert if it causes problems This change buys us 205,933 bytes of memory and 887 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for 1a14074 - Browse repository at this point
Copy the full SHA 1a14074View commit details -
Decrease string allocation in content_tag_string
When an unknonwn key is passed to the hash in `PRE_CONTENT_STRINGS` it returns nil, when you call "#{nil}" it allocates a new empty string. We can get around this allocation by using a default value `Hash.new { "".freeze }`. We can avoid the `to_sym` call by pre-populating the hash with a symbol key in addition to a string key. We can freeze some strings when using Array#* to reduce allocations. Array#join can take frozen strings. This change buys us 86,600 bytes of memory and 1,857 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for 2a4d430 - Browse repository at this point
Copy the full SHA 2a4d430View commit details -
No idea why on earth this hash key isn't already optimized by MRI, but it isn't. 💩 This change buys us 74,077 bytes of memory and 1,852 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for 2e95d2e - Browse repository at this point
Copy the full SHA 2e95d2eView commit details -
Cut string ActionView template allocations
The instrument method creates new strings, the most common action to instrument is "!render_template` so we can detect when that action is occurring and use a frozen string instead. This change buys us 113,714 bytes of memory and 1,790 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for 9b189a3 - Browse repository at this point
Copy the full SHA 9b189a3View commit details -
Cut string allocations in content_tag_string
content_tag's first argument is will generate a string with an html tag so `:a` will generate: `<a></a>`. When this happens, the symbol is implicitly `to_s`-d so a new string is allocated. We can get around that by using a frozen string instead which This change buys us 74,236 bytes of memory and 1,855 fewer objects per request.
Configuration menu - View commit details
-
Copy full SHA for e76a843 - Browse repository at this point
Copy the full SHA e76a843View commit details -
Avoid calling to_s on nil in journey/formatter
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
Configuration menu - View commit details
-
Copy full SHA for bff61ba - Browse repository at this point
Copy the full SHA bff61baView commit details -
Configuration menu - View commit details
-
Copy full SHA for 045cdd3 - Browse repository at this point
Copy the full SHA 045cdd3View commit details -
Only allocate new string when needed
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.
Configuration menu - View commit details
-
Copy full SHA for 3fb9e80 - Browse repository at this point
Copy the full SHA 3fb9e80View commit details -
Avoid hash duplication by skipping mutation
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).
Configuration menu - View commit details
-
Copy full SHA for 1993e2c - Browse repository at this point
Copy the full SHA 1993e2cView commit details -
Decrease allocations in transliterate
We can save a few objects by freezing the `replacement` string. We save a few more by down-casing the string in memory instead of allocating a new one. We save far more objects by checking for the default separator `"-"`, and using pre-generated regular expressions. We will save 209,231 bytes and 1,322 objects.
Configuration menu - View commit details
-
Copy full SHA for 57ba9cb - Browse repository at this point
Copy the full SHA 57ba9cbView commit details -
Configuration menu - View commit details
-
Copy full SHA for 0d7a714 - Browse repository at this point
Copy the full SHA 0d7a714View commit details -
Don't allocate array when not necessary
In the `tag_options` method an array is used to build up elements, then `Array#*` (which is an alias for `Array#join` is called to turn the array into a string. Instead of allocating an array to build a string, we can build the string we want from the beginning. Saved: 121,743 bytes 893 objects
Configuration menu - View commit details
-
Copy full SHA for 1f831fe - Browse repository at this point
Copy the full SHA 1f831feView commit details -
Configuration menu - View commit details
-
Copy full SHA for 005541b - Browse repository at this point
Copy the full SHA 005541bView commit details -
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
Configuration menu - View commit details
-
Copy full SHA for 4d2ccc1 - Browse repository at this point
Copy the full SHA 4d2ccc1View commit details -
Remove (another) array allocation
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
1Configuration menu - View commit details
-
Copy full SHA for 61dae88 - Browse repository at this point
Copy the full SHA 61dae88View commit details -
Use delete_if instead of each; delete(key)
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 ```
Configuration menu - View commit details
-
Copy full SHA for 22f5924 - Browse repository at this point
Copy the full SHA 22f5924View commit details