Speed up RSpec by deferring garbage collection

Updated . Posted . Visible to the public.

Update: This trick probably isn't very useful anymore in Ruby 2.x Show archive.org snapshot . The Ruby GC has improved a lot over the years.


Joe Van Dyk discovered Show archive.org snapshot that running the Ruby garbage collector only every X seconds can speed up your tests. I found that deferring garbage collection would speed up my RSpec examples by about 15%, but it probably depends on the nature of your tests. I also tried applying it to Cucumber features, but found no performance improvements.

Since Joe is using Test::Unit in his example, here is how to apply the same trick to RSpec.

First, copy this class to spec/support/deferred_garbage_collection.rb:

class DeferredGarbageCollection

  DEFERRED_GC_THRESHOLD = (ENV['DEFER_GC'] || 10.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

Then, in your spec_helper.rb, configure RSpec like seen below. Note that you might already have code hooked up to before(:all) and after(:all), so merge it together:

Spec::Runner.configure do |config|
  config.before(:all) do
    DeferredGarbageCollection.start
  end
  config.after(:all) do
    DeferredGarbageCollection.reconsider
  end
end

You can now enjoy faster specs.

Henning Koch
Last edit
Henning Koch
License
Source code in this card is licensed under the MIT License.
Posted by Henning Koch to makandra dev (2011-01-21 11:35)