1. 03 9月, 2016 1 次提交
  2. 07 8月, 2016 2 次提交
  3. 19 5月, 2016 1 次提交
  4. 01 2月, 2016 1 次提交
  5. 19 9月, 2015 1 次提交
  6. 20 7月, 2015 1 次提交
    • 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. 05 1月, 2015 1 次提交
  8. 17 12月, 2014 1 次提交
    • S
      `update_column` take ruby-land input, not database-land input · dd8b5fb9
      Sean Griffin 提交于
      In the case of serialized columns, we would expect the unserialized
      value as input, not the serialized value. The original issue which made
      this distinction, #14163, introduced a bug. If you passed serialized
      input to the method, it would double serialize when it was sent to the
      database. You would see the wrong input upon reloading, or get an error
      if you had a specific type on the serialized column.
      
      To put it another way, `update_column` is a special case of
      `update_all`, which would take `['a']` and not `['a'].to_yaml`, but you
      would not pass data from `params` to it.
      
      Fixes #18037
      dd8b5fb9
  9. 26 6月, 2014 2 次提交
  10. 14 6月, 2014 1 次提交
    • S
      Introduce an Attribute object to handle the type casting dance · 6f08db05
      Sean Griffin 提交于
      There's a lot more that can be moved to these, but this felt like a good
      place to introduce the object. Plans are:
      
      - Remove all knowledge of type casting from the columns, beyond a
        reference to the cast_type
      - Move type_cast_for_database to these objects
      - Potentially make them mutable, introduce a state machine, and have
        dirty checking handled here as well
      - Move `attribute`, `decorate_attribute`, and anything else that
        modifies types to mess with this object, not the columns hash
      - Introduce a collection object to manage these, reduce allocations, and
        not require serializing the types
      6f08db05
  11. 10 6月, 2014 1 次提交
    • S
      Make `_before_type_cast` actually be before type cast · c93dbfef
      Sean Griffin 提交于
      - The following is now true for all types, all the time
        - `model.attribute_before_type_cast == given_value`
        - `model.attribute == model.save_and_reload.attribute`
        - `model.attribute == model.dup.attribute`
        - `model.attribute == YAML.load(YAML.dump(model)).attribute`
      - Removes the remaining types implementing `type_cast_for_write`
      - Simplifies the implementation of time zone aware attributes
      - Brings tz aware attributes closer to being implemented as an attribute
        decorator
      - Adds additional point of control for custom types
      c93dbfef
  12. 03 6月, 2014 1 次提交
  13. 02 6月, 2014 1 次提交
    • S
      Remove most code related to serialized properties · 90c8be76
      Sean Griffin 提交于
      Nearly completely implemented in terms of custom properties.
      `_before_type_cast` now stores the raw serialized string consistently,
      which removes the need to keep track of "state". The following is now
      consistently true:
      
      - `model.serialized == model.reload.serialized`
      - A model can be dumped and loaded infinitely without changing
      - A model can be saved and reloaded infinitely without changing
      90c8be76
  14. 31 5月, 2014 1 次提交
    • S
      Rename attribute related instance variables to better express intent · eb6cee9c
      Sean Griffin 提交于
      `@attributes` was actually used for `_before_type_cast` and friends,
      while `@attributes_cache` is the type cast version (and caching is the
      wrong word there, but I'm working on removing the conditionals around
      that). I opted for `@raw_attributes`, because `_before_type_cast` is
      also semantically misleading. The values in said hash are in the state
      given by the form builder or database, so raw seemed to be a good word.
      eb6cee9c
  15. 30 5月, 2014 2 次提交
  16. 06 4月, 2014 1 次提交
  17. 04 7月, 2013 3 次提交
  18. 03 7月, 2013 2 次提交
  19. 22 11月, 2012 1 次提交
    • J
      Don't allocate new strings in compiled attribute methods · ae934aef
      Jon Leighton 提交于
      This improves memory and performance without having to use symbols which
      present DoS problems. Thanks @headius and @tenderlove for the
      suggestion.
      
      This was originally committed in
      f1765019, and then reverted in
      d3494903 due to it causing problems in a
      real application. This second attempt should solve that.
      
      Benchmark
      ---------
      
      require 'active_record'
      require 'benchmark/ips'
      
      ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
      
      class Post < ActiveRecord::Base
        connection.create_table :posts, force: true do |t|
          t.string :name
        end
      end
      
      post = Post.create name: 'omg'
      
      Benchmark.ips do |r|
        r.report('Post.new')          { Post.new name: 'omg' }
        r.report('post.name')         { post.name }
        r.report('post.name=')        { post.name = 'omg' }
        r.report('Post.find(1).name') { Post.find(1).name }
      end
      
      Before
      ------
      
      Calculating -------------------------------------
                  Post.new      1419 i/100ms
                 post.name      7538 i/100ms
                post.name=      3024 i/100ms
         Post.find(1).name       243 i/100ms
      -------------------------------------------------
                  Post.new    20637.6 (±12.7%) i/s -     102168 in   5.039578s
                 post.name  1167897.7 (±18.2%) i/s -    5186144 in   4.983077s
                post.name=    64305.6 (±9.6%) i/s -     317520 in   4.998720s
         Post.find(1).name     2678.8 (±10.8%) i/s -      13365 in   5.051265s
      
      After
      -----
      
      Calculating -------------------------------------
                  Post.new      1431 i/100ms
                 post.name      7790 i/100ms
                post.name=      3181 i/100ms
         Post.find(1).name       245 i/100ms
      -------------------------------------------------
                  Post.new    21308.8 (±12.2%) i/s -     105894 in   5.053879s
                 post.name  1534103.8 (±2.1%) i/s -    7634200 in   4.979405s
                post.name=    67441.0 (±7.5%) i/s -     337186 in   5.037871s
         Post.find(1).name     2681.9 (±10.6%) i/s -      13475 in   5.084511s
      ae934aef
  20. 01 11月, 2012 1 次提交
  21. 12 10月, 2012 2 次提交
    • J
      Don't allocate new strings in compiled attribute methods · f1765019
      Jon Leighton 提交于
      This improves memory and performance without having to use symbols which
      present DoS problems. Thanks @headius and @tenderlove for the
      suggestion.
      
      Benchmark
      ---------
      
      require 'active_record'
      require 'benchmark/ips'
      
      ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database:
      ':memory:')
      
      class Post < ActiveRecord::Base
        connection.create_table :posts, force: true do |t|
          t.string :name
        end
      end
      
      post = Post.create name: 'omg'
      
      Benchmark.ips do |r|
        r.report('Post.new')          { Post.new name: 'omg' }
        r.report('post.name')         { post.name }
        r.report('post.name=')        { post.name = 'omg' }
        r.report('Post.find(1).name') { Post.find(1).name }
      end
      
      Before
      ------
      
      Calculating -------------------------------------
                  Post.new      1419 i/100ms
                 post.name      7538 i/100ms
                post.name=      3024 i/100ms
         Post.find(1).name       243 i/100ms
      -------------------------------------------------
                  Post.new    20637.6 (±12.7%) i/s -     102168 in   5.039578s
                 post.name  1167897.7 (±18.2%) i/s -    5186144 in   4.983077s
                post.name=    64305.6 (±9.6%) i/s -     317520 in   4.998720s
         Post.find(1).name     2678.8 (±10.8%) i/s -      13365 in   5.051265s
      
      After
      -----
      
      Calculating -------------------------------------
                  Post.new      1431 i/100ms
                 post.name      7790 i/100ms
                post.name=      3181 i/100ms
         Post.find(1).name       245 i/100ms
      -------------------------------------------------
                  Post.new    21308.8 (±12.2%) i/s -     105894 in   5.053879s
                 post.name  1534103.8 (±2.1%) i/s -    7634200 in   4.979405s
                post.name=    67441.0 (±7.5%) i/s -     337186 in   5.037871s
         Post.find(1).name     2681.9 (±10.6%) i/s -      13475 in   5.084511s
      f1765019
    • J
      Revert "Key the attributes hash with symbols" · 9e5f7cc6
      Jon Leighton 提交于
      This reverts commit 86c3dfbd.
      
      Conflicts:
      	activerecord/lib/active_record/attribute_methods/read.rb
      
      Reason: whilst this increased performance, it also presents a DoS risk
      via memory exhaustion if users were allowing user input to dictate the
      arguments of read/write_attribute. I will investigate alternative ways
      to cut down on string allocations here.
      9e5f7cc6
  22. 22 9月, 2012 1 次提交
  23. 31 8月, 2012 1 次提交
    • J
      Key the attributes hash with symbols · 86c3dfbd
      Jon Leighton 提交于
      This is a performance/GC optimisation.
      
      In theory, this could be optimised by the implementation (last time I
      checked, this would have no effect on JRuby). But in practise, this make
      attribute access faster.
      86c3dfbd
  24. 11 2月, 2012 1 次提交
  25. 07 2月, 2012 2 次提交
  26. 16 12月, 2011 1 次提交
  27. 01 12月, 2011 3 次提交
  28. 15 11月, 2011 1 次提交
  29. 06 10月, 2011 1 次提交
  30. 05 10月, 2011 1 次提交