Ruby’s DBI or ActiveRecord
While creating a small CGI web application in Ruby the question came up about how much slower ActiveRecord is than DBI. Considering that ActiveRecord is initialized each time the CGI runs the performance hit could be significant.
So why not use Rails instead? The server that I am running the application on has limited resources. Rails is reported to need about 20 MB of memory and the node I have is already paging out memory to disk.
To emulate the webserver getting hit repeatedly with connections I created a connect_dbi.rb and and connect_ar.rb that insert the same row into a Tests database table. The ActiveRecord test also has the model file test.rb
The test was run using a PostGreSQL database on Ubuntu 5.10 with Ruby 1.8.4. The table was truncated between tests. I just wanted to get an idea of the performance difference between ActiveRecord and DBI. So this isn’t the strictest performance test but does provide an idea of the magnitude of difference.
The test was executed from the command line using “ruby -e” to call the connect_dbi.rb and connect_ar.rb files 100 times each. This creates a new database connection each time the script is executed. ActiveRecord generates a series of error messages about unavailable database adapters each time it is started so these messages were capatured in the activeError file. DBI doesn’t produce any errors but I wanted to keep the execution as similar as possible so there is also a dbiError file created.
connect_dbi.rb
#! /usr/bin/ruby -w
require 'rubygems'
require 'dbi'
dbh = DBI.connect('dbi:Pg:tmp_test:localhost','ruby_user','ruby_pass')
begin
dbh.transaction do |dbh|
dbh.prepare("INSERT INTO tests(rank, created_at, message) VALUES(?,?,?)") do |sth|
sth.execute(5, Time.now, 'abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ')
end
end
rescue DBI::ProgrammingError => exception
puts "Exception: #{exception.message}"
end
connect_ar.rb
#! /usr/bin/ruby -w
require 'rubygems'
require_gem 'activerecord'
ActiveRecord::Base.establish_connection(
:adapter => "postgresql",
:host => "localhost",
:username => "ruby_user",
:password => "ruby_pass",
:database => "tmp_test"
)
test = Test.new("rank" => 5, "created_at" => "#{Time.now}", "message" => 'abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz abcdefghijklmnopqrstuvwxyz ')
test.save
test.rb
class Test < ActiveRecord::Base
end
The GNU/Linux time command was used to obtain timings.
As the results show DBI appears to be about three times faster than using ActiveRecord. This is most likely because of the initialization ActiveRecord does each time the connection is established. Considering that the test is only using one table and one ActiveRecord model class this is a fairly significant difference.
~/projects/dbi_test $ time ruby -e '100.times { %x{./connect_ar.rb}}' 2> activeError
real 0m25.916s
user 0m21.575s
sys 0m2.807s
~/projects/dbi_test $ time ruby -e '100.times { %x{./connect_dbi.rb}}' 2> dbiError
real 0m8.154s
user 0m6.620s
sys 0m0.733s
All results are in seconds. Each test was run ten times.DBI Results
| Mean | Standard Deviation | |
|---|---|---|
| Real | 7.7133 | 0.9448 |
| User | 6.2027 | 0.8530 |
| Sys | 6.2027 | 0.2760 |
ActiveRecord Results
| Mean | Standard Deviation | |
|---|---|---|
| Real | 26.9003 | 1.8849 |
| User | 21.9256 | 1.4959 |
| Sys | 2.8038 | 0.4610 |
March 30th, 2007 at 1:03 am
I would like to see how much slower your ActiveRecord version is if you use fastcgi.
http://wiki.rubygarden.org/Ruby/page/show/FCGIRubyPerformance