Ruby Techniques Revealed: Autoload
There's plenty of stuff in Ruby that I've either not noticed before, noticed but forgotten about, or otherwise failed to realize the utility of. Add to that all the awesome Ruby tricks and techniques I'm seeing in people's code over on Github lately and.. we need a new series here: Ruby Techniques Revealed!
Disclaimer: I'm not promising you won't already know about anything I "reveal." A lot of you are far better than me at knowing all of Ruby's dark corners. I'm just going to shine a spotlight in the direction of things I don't see used very often that I think are cool.
Autoload - Load stuff only when it's needed
I was going through the source for Thin and noticed that instead of using
require, Marc-Andre Cournoyer was using a method called
autoload to load thin's constituent parts. Specifically:
autoload :Command, 'thin/command' autoload :Connection, 'thin/connection' autoload :Daemonizable, 'thin/daemonizing' autoload :Logging, 'thin/logging'
This intrigued me so I hit Google and came across a little demo of autoload by Mike Subelsky.
autoload works in a similar way to
require, but it only loads the file specified when a constant of your choosing is accessed/used for the first time. This constant would usually be the name of the class provided by the other source file (but it doesn't have to be, as Mike demonstrates).
Let's say you have a file called
mylibrary.rb containing the following code:
puts "I was loaded!" class MyLibrary end
irb, let's use
require to load the "library":
irb(main):001:0> require 'mylibrary' I was loaded! => true
require works straight away, the
puts method gets executed immediately. So let's restart
irb and see what happens if we use
irb(main):001:0> autoload :MyLibrary, 'mylibrary' => nil irb(main):002:0> MyLibrary.new I was loaded! => #<MyLibrary:0x0b1jef>
puts method doesn't get executed until we try and use
autoload has prevented the loading of
mylibrary.rb until we really needed it.
Detecting Autoloadable Classes
If you want to detect whether a certain class is awaiting autoloading, you can check, like so:
autoload :X, 'x' puts "X is awaiting loading" if autoload?(:X)
Just beware ye threads..
Further Googling led me to some interesting discussions about
autoload. Back in December 2008, a whole group of Ruby luminaries got into a discussion about autoload's issues with threads. Turns out that even though several projects have been adopting autoload in anger recently, there are some concerns surrounding how thread safe autoload is. The proposed solution is to have a mutex between all autoloads, but I haven't yet established how far work on this (if any) has gone.
There was a similar discussion back in early 2008, started by Yehuda Katz (of Merb fame) that I'd advise you read if threading is going to be a big deal to you. He seems to imply that big issues only crop up under heavy concurrency situations, but the problem is there regardless. There seem to be similar issues around
require too though so I'll be taking the "cross that bridge when I get to it" approach.. ;-)