Skip to main content

RSpec speed-up (24.6%) by tweaking ruby garbage collection

·237 words·2 mins· ·
Ruby Rails Rspec Speed Garbage Collection GC
Ariejan de Vroom
Author
Ariejan de Vroom
Jack of all Trades, Professional Software Craftsman

[Today I learned][1] that Ruby garbage collection can be of huge importance to performance. More precisely, if Ruby does a lot of garbage collection it may slow down your code. Running garbage collection only every 10 or 20 seconds when running specs may increase performance dramatically.

At this time specs for Ariejan.net take an average of 25.29s to run. This is not bad, but in my opinion faster specs are better. After tweaking ruby garbage collection I got my specs to run in 19.05s, a 24.6% speed increase! [1]: http://37signals.com/svn/posts/2742-the-road-to-faster-tests ~ So, how do you speed up your tests?

The key is that you don’t want ruby to decide when to do garbage collection for you. Instead, we’ll tell Ruby when to do this, and we’ll let it do it every 15 seconds.

To set this up for RSpec create a file spec/support/deferred_garbage_collection.rb:

class DeferredGarbageCollection

  DEFERRED_GC_THRESHOLD = (ENV['DEFER_GC'] || 15.0).to_f

  @@last_gc_run = Time.now

  def self.start
    GC.disable if DEFERRED_GC_THRESHOLD > 0
  end

  def self.reconsider
    if DEFERRED_GC_THRESHOLD > 0 && Time.now - @@last_gc_run >= DEFERRED_GC_THRESHOLD
      GC.enable
      GC.start
      GC.disable
      @@last_gc_run = Time.now
    end
  end
end

Next, add the following to your spec/spec_helper.rb so rspec will use our deferred garbage collection.

config.before(:all) do
  DeferredGarbageCollection.start
end

config.after(:all) do
  DeferredGarbageCollection.reconsider
end

Now, when you run rake spec you should see a nice speed increase. Try to alter the threshold value a bit to see what gives your best performance:

DEFER_GC=20 rake spec

Enjoy!

Related

RSpec'ing with Time.now
·174 words·1 min
General Ruby Rails Rspec Test Time
Upgrading to Mongoid Beta 6
·197 words·1 min
Ruby Rails Mongoid Monogdb
Bundler + Passenger with Rails 2.3.5? Yes, please!
·236 words·2 mins
Ruby Rails Bundler Passenger