I recently upgraded one of my applications to Rails 2.2.2. Having done that, I've encountered a strange performance bug that has caused renders that used to complete in a fraction of a second to take up to 10 seconds.
I've profiled the issue, and here are the results I've come up with. It looks like the issue is in the real_connect
method of the Mysql class. My understanding is that the Ruby real_connect
method is a wrapper around the C mysql_real_connect()
function. This would lead me to believe that the issue must be with the database, since I've encountered the same problem when running the code on Windows and Linux (the database server is a separate system). I don't, however, believe this is the case, because when I roll back to a previous version (pre Rails 2.2.2) from my subversion repository, the performance issue goes away. This would seem the indicate that there is some kind of bug in ActiveRecord.
How do I go about identifying and fixing this bug? Does anyone have any insight? Is there something I'm missing?
Update: I just created a small profiler script to test the Mysql.real_connect method, and it appears that the problem isn't in Rails, but in the MySQL gem or the database server itself.
Upon running the following code:
result = RubyProf.profile do
5.times do
begin
# connect to the MySQL server
dbh = Mysql.real_connect(ip, user, pass, db)
# get server version string and display it
puts "Server version: " + dbh.get_server_info
rescue Mysql::Error => e
puts "Error code: #{e.errno}"
puts "Error message: #{e.error}"
puts "Error SQLSTATE: #{e.sqlstate}" if e.respond_to?("sqlstate")
ensure
# disconnect from server
dbh.close if dbh
end
end
end
printer = RubyProf::FlatPrinter.new(result)
printer.print(STDOUT, 0)
I came up with this performance result:
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Server version: 5.0.32-Debian_7etch3-log
Thread ID: 18998180
Total: 50.402000
%self total self wait child calls name
99.99 50.40 50.40 0.00 0.00 5 <Class::Mysql>#real_connect (ruby_runtime:0}
0.00 0.00 0.00 0.00 0.00 10 IO#write (ruby_runtime:0}
0.00 0.00 0.00 0.00 0.00 5 Mysql#get_server_info (ruby_runtime:0}
0.00 0.00 0.00 0.00 0.00 5 Kernel#puts (ruby_runtime: 0}
0.00 0.00 0.00 0.00 0.00 5 String#+ (ruby_runtime:0}
0.00 0.00 0.00 0.00 0.00 5 Mysql#initialize (ruby_runtime:0}
0.00 50.40 0.00 0.00 50.40 1 Integer#times (ruby_runtime:0}
0.00 50.40 0.00 0.00 50.40 1 Global#[No method] (tmp/mysql_test/test.rb:12}
0.00 0.00 0.00 0.00 0.00 5 Mysql#close (ruby_runtime: 0}
It seems as though the problem isn't in ActiveRecord, it's either in the MySQL gem or in the database. Where do I go from here?