Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Commits on Jul 30, 2015
  1. @schneems

    String#freeze optimizations

    schneems authored
  2. @schneems

    Decrease allocations in transliterate

    schneems authored
    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.
  3. @schneems

    Decrease string allocations in apply_inflections

    schneems authored
    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.
Commits on Jul 28, 2015
  1. @robin850
  2. @robin850
Commits on Jul 24, 2015
  1. @matthewd

    Merge pull request #20928 from matthewd/unload-interlock

    matthewd authored
    We need stricter locking before we can unload
Commits on Jul 23, 2015
  1. @matthewd

    Don't apply locking around basic #load / #require

    matthewd authored
    That's outside our remit, and dangerous... if a caller has their own
    locking to protect against the natural race danger, we'll deadlock
    against it.
Commits on Jul 21, 2015
  1. @matthewd

    Handle thread death during lock acquisition

    matthewd authored
    Specifically, clean up if the thread is killed while it's blocked
    awaiting the lock... if we get killed on some other arbitrary line, the
    result remains quite undefined.
  2. @matthewd
Commits on Jul 20, 2015
  1. @matthewd

    Order of execution is only guaranteed if upgrading

    matthewd authored
    If the thread isn't yet holding any form of lock, it has no claim over
    what may / may not run while it's blocked.
  2. @thedarkone

    Fix ShareLock issues.

    thedarkone authored
Commits on Jul 19, 2015
  1. @matthewd

    We need stricter locking before we can unload

    matthewd authored
    Specifically, the "loose upgrades" behaviour that allows us to obtain an
    exclusive right to load things while other requests are in progress (but
    waiting on the exclusive lock for themselves) prevents us from treating
    load & unload interchangeably: new things appearing is fine, but they do
    *not* expect previously-present constants to vanish.
    
    We can still use loose upgrades for unloading -- once someone has
    decided to unload, they don't really care if someone else gets there
    first -- it just needs to be tracked separately.
  2. @sgrif
  3. @sgrif

    Merge pull request #20946 from schneems/schneems/let-it-go

    sgrif authored
    Freeze string literals when not mutated.
  4. @schneems

    Freeze string literals when not mutated.

    schneems authored
    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)
  5. @kaspth

    Merge pull request #20944 from repinel/fix-time-with-zone-eql

    kaspth authored
    Fix `TimeWithZone#eql?` to handle `TimeWithZone` created from `DateTime`
  6. @repinel

    Fix `TimeWithZone#eql?` to handle `TimeWithZone` created from `DateTime`

    repinel authored
    Before:
    
    ```ruby
      twz = DateTime.now.in_time_zone
      twz.eql?(twz.dup) => false
    ```
    
    Now:
    
    ```ruby
      twz = DateTime.now.in_time_zone
      twz.eql?(twz.dup) => true
    ```
    
    Please notice that this fix the `TimeWithZone` comparison to itself,
    not to `DateTime`. Based on #3725, `DateTime` should not be equal to
    `TimeWithZone`.
  7. @sgrif

    Merge pull request #20839 from TheBlasfem/added_examples_dateandtime_…

    sgrif authored
    …calculations
    
    Added examples to DateAndTime::Calculations [ci skip]
Commits on Jul 18, 2015
  1. @TheBlasfem
Commits on Jul 17, 2015
  1. @imanel @sgrif

    ActiveSupport::HashWithIndifferentAccess select and reject should ret…

    imanel authored sgrif committed
    …urn enumerator if called without block
  2. @jonatack

    [skip ci] Lookup can be a noun but it is not a verb

    jonatack authored
    Various grammar corrections and wrap to 80 characters.
Commits on Jul 15, 2015
  1. @rafaelfranca

    Merge pull request #20887 from tgxworld/ar_callbacks

    rafaelfranca authored
    Revert "Revert "Reduce allocations when running AR callbacks.""
  2. @tgxworld

    Revert "Revert "Reduce allocations when running AR callbacks.""

    tgxworld authored
    This reverts commit bdc1d32.
    
    Before:
    Calculating -------------------------------------
                            22.000  i/100ms
    -------------------------------------------------
                            229.700  (± 0.4%) i/s -      1.166k
    Total Allocated Object: 9939
    
    After:
    Calculating -------------------------------------
                            24.000  i/100ms
    -------------------------------------------------
                            246.443  (± 0.8%) i/s -      1.248k
    Total Allocated Object: 7939
    
    ```
    begin
      require 'bundler/inline'
    rescue LoadError => e
      $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
      raise e
    end
    
    gemfile(true) do
      source 'https://rubygems.org';
      # gem 'rails', github: 'rails/rails', ref: 'bdc1d329d4eea823d07cf010064bd19c07099ff3'
      gem 'rails', github: 'rails/rails', ref: 'd2876141d08341ec67cf6a11a073d1acfb920de7'
      gem 'arel', github: 'rails/arel'
      gem 'sqlite3'
      gem 'benchmark-ips'
    end
    
    require 'active_record'
    require 'benchmark/ips'
    
    ActiveRecord::Base.establish_connection('sqlite3::memory:')
    
    ActiveRecord::Migration.verbose = false
    
    ActiveRecord::Schema.define do
      create_table :users, force: true do |t|
        t.string :name, :email
        t.boolean :admin
        t.timestamps null: false
      end
    end
    
    class User < ActiveRecord::Base
      default_scope { where(admin: true) }
    end
    
    admin = true
    
    1000.times do
      attributes = {
        name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
        email: "foobar@email.com",
        admin: admin
      }
    
      User.create!(attributes)
    
      admin = !admin
    end
    
    GC.disable
    
    Benchmark.ips(5, 3) do |x|
      x.report { User.all.to_a }
    end
    
    key =
      if RUBY_VERSION < '2.2'
        :total_allocated_object
      else
        :total_allocated_objects
      end
    
    before = GC.stat[key]
    User.all.to_a
    after = GC.stat[key]
    puts "Total Allocated Object: #{after - before}"
    ```
Commits on Jul 13, 2015
  1. @jdantonio

    Replaced `ActiveSupport::Concurrency::Latch` with concurrent-ruby.

    jdantonio authored
    The concurrent-ruby gem is a toolset containing many concurrency
    utilities. Many of these utilities include runtime-specific
    optimizations when possible. Rather than clutter the Rails codebase with
    concurrency utilities separate from the core task, such tools can be
    superseded by similar tools in the more specialized gem. This commit
    replaces `ActiveSupport::Concurrency::Latch` with
    `Concurrent::CountDownLatch`, which is functionally equivalent.
Commits on Jul 11, 2015
  1. @kaspth

    Merge pull request #20838 from TheBlasfem/improve_duplicable_document…

    kaspth authored
    …ation
    
    Improve duplicable documentation [ci skip]
Commits on Jul 10, 2015
  1. @TheBlasfem
  2. @tenderlove

    Merge pull request #17102 from matthewd/load-interlock

    tenderlove authored
    Concurrent load interlock (rm Rack::Lock)
  3. @kaspth
  4. @rafaelfranca

    Merge pull request #20828 from Sirupsen/hash-indifferent-dup-default-…

    rafaelfranca authored
    …proc
    
    active_support/indifferent_access: fix not raising when default_proc does
  5. @Sirupsen
  6. @Sirupsen
Commits on Jul 8, 2015
  1. @kaspth

    Merge pull request #20784 from kaspth/great-expectations

    kaspth authored
    Add method call assertions for internal use.
  2. @kaspth

    Add method call assertions for internal use.

    kaspth authored
    Add `assert_called` and `assert_not_called` to boil down the boilerplate we need to write
    to assert methods are called certain number of times.
  3. @matthewd
  4. @matthewd
Something went wrong with that request. Please try again.