A criticism often leveraged against Ruby on Rails is that it’s slow. It’s true that the Ruby
language is slower at some things than other languages used in web development con-
texts. That just means that you as a developer need to be aware of where Ruby and
Rails can eat up valuable processor cycles. Then you can avoid those hot-spots by
choosing less processor-hungry alternatives to some of the great Rails sugar when it
doesn’t provide justifiable benefits.
Once cause of slowness I’ve found is in converting the results of a SQL query into
ActiveRecord objects. A row from an SQL query result set is just a set of key-value pairs;
in other words, a hash. ActiveRecord objects are great in that they come bundled up
with methods that let you traverse object relationships, and they also contain methods
you’ve written into the classes to facilitate custom behavior. But along with all the sugar
that ActiveRecord provides comes a heavy overhead of creating the object itself.
Very often, especially when you’re selecting records to display a web page, all you need
are the key-value pairs. A hash would suffice, and it turns out getting your results out
of the database as hashes is much faster—more than 50% faster than requesting
ActiveRecord objects.
Whereas a regular query that retrieves ActiveRecord objects looks like this:
MyObject.find(:all)
a query that returns hashes looks like this:
MyObject.connection.select_all("select * from my_objects")
True, you resort to SQL here, but in slow pages where you need to eke out that last bit
of render-time performance, the trade-off can be worth it. In a test of retrieving 40
thousand objects on a MacBook Pro 2.33 Ghz Intel Core 2 Duo, the ActiveRecord
approach took seven seconds of Ruby time, while the hash method took three.
The other caveat worth noting when replacing ActiveRecord queries with hash queries
is that objects and hashes are accessed differently. You access objects with dot notation:
my_object.foo versus my_object['foo']. But that’s exactly the problem taken care of by
our core hash extension! Using this extension, you can cherry-pick slow ActiveRecord
queries that aren’t using all the “extras” given to you by the ActiveRecord object itself,
and swap out the query to boost performance.
?