Improving the load time of your application

performance loadtime ruby sinatra monk

10|06|2010

Step 0: Benchmark!

(Disclaimer: the code that follows is in no way a prescription on how to write good benchmarking code but was simply written in a minute :-)

require "benchmark"
module Kernel
  alias :basic_require :require
  def timed_require(lib)
    t = Benchmark.realtime { basic_require(lib) }
    $__timings << [lib, t]
  end

  def BM
    $__timings = []
    Kernel.send :alias_method, :require, :timed_require
    yield
    Kernel.send :alias_method, :require, :basic_require
    puts "## Total: #{$__timings.inject(0) { |acc, (_, t)| acc + t}}"
    $__timings.
      reject  { |e| e[1] < 0.10 }.
      sort_by { |e| e[1] * -1 }.each do |lib, t|
      puts " - %s (%2.5f)" % [lib, t]
    end
  end
end

All of my requires

BM {
require "open-uri"
require "fileutils"
require "forwardable"
require "ohm"
require "ohm/contrib"
require "peons"
require "haml"
require "less"
require "rtopia"
require "i18n"
require "active_support"
require "sinatra/base"
require "sinatra/security"
require "sinatra/support"
require "sinatra/minify"
require "whitelist"
require "spawn"
require "ffaker"
require "rdiscount"
require "imagery"
require "sinatra/content_for"
require "sinatra/i18n"
require "pagination"
require "bullhorn"
require "money"
require "twitter_oauth"

Dir["./lib/*.rb"].each { |lib| require lib }
}

--> Load time before doing anything: 6.54 seconds

What stood out?

  • ActiveSupport: 1.10 seconds
  • Less: 1.06 seconds
  • Twitter Oauth: 0.90 seconds
  • Crack: 0.20 seconds

(Also I found some other files in lib which I wasn't really using anymore.)

Step 1: Remove deprecated code

Most probably in a project that spans more than a couple of months, you'll have probably used a library somewhere along the way and forgot to unrequire or remove it. In my case we weren't using twitter_oauth anymore (and a couple of other ruby files in ./lib).

Step 2: Trim some of the gems?

I was using the madmimi gem to integrate to their webservice, but really, I was only using literally one method which was MadMimi#send_mail. So I trimmed it down to the bare essentials:

Side note: I might try and do a fork which only requires the necessary files (specifically the Crack library) when it's needed, and possibly make it more modular probably using autoload or something similar.

Step 3: Forget about LESS (at least less in ruby)

Less takes too much baggage with it quite honestly, and I don't even remember why I chose it over SASS or SCSS.

In short, I removed the require 'less' and simply did a quick sass-convert --from less --to sass app/views/css/*. The conversion was flawless.

Step 4: Upgrade to ActiveSupport 3.0.0

(For all activesupport haters, yes, I will probably do time zones on my own later :-)

Basically I was using ActiveSupport 2.3.8, which took with it everything that it shouldn't.

After upgrading to activesupport 3 and doing a require "active_support/time", the load time dropped to 0.12 from 1.10 seconds).

Step 5: Enjoy the faster load time:

From 6.54 seconds down to 2.80 seconds. You might say that 3 seconds doesn't mean anything really, but there are cases where a tenth of a second can spell the different between a gold or silver medal :-)

blog comments powered by Disqus