1. 31 7月, 2015 7 次提交
    • S
      Use delete_if instead of each; delete(key) · 22f59240
      schneems 提交于
      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
      ```
      22f59240
    • S
      Remove (another) array allocation · 61dae882
      schneems 提交于
      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
      61dae882
    • S
      Remove array allocation · 4d2ccc11
      schneems 提交于
      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
      4d2ccc11
    • S
      Avoid hash duplication by skipping mutation · 1993e2cc
      schneems 提交于
      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).
      1993e2cc
    • S
      Only allocate new string when needed · 3fb9e802
      schneems 提交于
      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.
      3fb9e802
    • S
      Freeze a string in comparator · 045cdd3a
      schneems 提交于
      Saves 888 string objects per request.
      045cdd3a
    • S
      Avoid calling to_s on nil in journey/formatter · bff61ba2
      schneems 提交于
      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
      bff61ba2
  2. 30 7月, 2015 5 次提交
    • S
      Reduce hash allocations in route_set · 1a14074f
      schneems 提交于
      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.
      1a14074f
    • S
      Decrease route_set allocations · 0cbec58a
      schneems 提交于
      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.
      0cbec58a
    • S
      Speed up journey missing_keys · 097ec6fb
      schneems 提交于
      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.
      097ec6fb
    • S
      Speed up journey extract_parameterized_parts · 9b825881
      schneems 提交于
      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
      9b825881
    • S
      Decrease string allocations in url_options · 83ee043c
      schneems 提交于
      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.
      83ee043c
  3. 28 7月, 2015 3 次提交
  4. 26 7月, 2015 1 次提交
    • M
      Fix params_wrapper doc [ci skip] · edda07b2
      Mehmet Emin İNAÇ 提交于
      This feature also works with `PUT`, `PATCH` and `DELETE` requests.
      Also developers can add `:url_encoded_form` and `:multipart_form`
      into the `:format` for wrapping url encoded or multipart form data.
      edda07b2
  5. 22 7月, 2015 6 次提交
  6. 20 7月, 2015 2 次提交
    • R
      Fix state being carried over from previous transaction · 12b0b26d
      Roque Pinel 提交于
      This clears the transaction record state when the transaction finishes
      with a `:committed` status.
      
      Considering the following example where `name` is a required attribute.
      Before we had `new_record?` returning `true` for a persisted record:
      
      ```ruby
        author = Author.create! name: 'foo'
        author.name = nil
        author.save        # => false
        author.new_record? # => true
      ```
      12b0b26d
    • S
      Freeze string literals when not mutated. · 5bb1d4d2
      schneems 提交于
      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)
      5bb1d4d2
  7. 19 7月, 2015 2 次提交
  8. 18 7月, 2015 10 次提交
  9. 17 7月, 2015 3 次提交
  10. 16 7月, 2015 1 次提交