Home > Rants > Rails 2.2 Connection Pools + Mongrel Handlers = Slow

Rails 2.2 Connection Pools + Mongrel Handlers = Slow

December 17th, 2008

Rails 2.2 doesn’t like Mongrel handlers.  Specifically, the Rails 2.2 connection pool doesn’t.  More specifically, the connection pool doesn’t like a bunch of random threads taking its connections and not giving them back.

After a day of head banging (yah!!  rock on!!), I devised the following monkey patch solution to get our Mongrel handlers back on Rails’ good graces:

module ActiveRecord
  module ConnectionAdapters
   class ConnectionPool
    def release_connection(conn_id = nil)
     conn_id ||= current_connection_id
     conn = @reserved_connections.delete(conn_id)
     checkin conn if conn
    end
   end

   class ConnectionHandler
    def clear_my_connection!(conn_id)
     @connection_pools.each_value {|pool| pool.release_connection(conn_id) }
    end
   end
end
end

After you paste that into a file in your initializers directory, you’ll just need to call the clear_my_connection! method whenever you exit a Mongrel handler (or other type of Rails thread) that has accessed an ActiveRecord find.  We’re doing this like so:

ActiveRecord::Base.connection_handler.clear_my_connection!(Thread.current.object_id)

Hope this saves someone else a day of unproductive Googling when they upgrade to 2.2 and their Mongrel handlers suddenly start taking 5 seconds each (the time until the Thread’s connection will naturally timeout) to execute.

If anyone else has solved this in a more elegant way, you speak up now, y’hear?

Bill Rants

  1. December 26th, 2008 at 13:40 | #1

    Hi,

    thanks for sharing this. I’m having the same kind of issue while using ActiveRecord 2.2.2 outside Rails (in multithreaded Ramaze): the n-1 first queries (with n = activerecord pool size) are fast, then the n-th query shows 2 thread and runs during 5 seconds.

    I’ll try applying what you did.

    Did you came up with something else since you wrote this ?

    cheers

    – Thibaut

  2. February 3rd, 2009 at 12:15 | #2

    Working under Rails2.3 (with Rails::Metal) I got the same issue.

    It’s in the documentation of ActiveRecord, you have to manualy release the connection that ActiveRecord fetch from the pool when you no longer need them (at the end of the Rack process).

    So I just implemented a Rack Middleware to free them, it is a bit cleaner but does exactly the same thing (or rather make ActiveRecord do the same thing) and can be reused in any kind of rack stack using active record

    http://gist.github.com/57640

    Otherwise in current ActiveRecord version you could just drop your code and execute ActiveRecord::Base.clear_active_connections! when you want to release the connection into the pool. It does the same stuff than you patch.

  3. Ryan Alyea
    June 26th, 2009 at 08:51 | #3

    I’m working on an XMPP server where each client gets it’s own thread for the length of the connection that could be hours or more. I noticed that ActiveRecord started failing at around 5 connections with long waits or timeouts during Authentication where it would look at the appropriate user/pass in the database. A quick DTrace/Instruments session pointed to it blocking until a connection from the pool is available.

    Renaud explained it above: Since each thread is still alive, ActiveRecord keeps that pool record alive. Manually releasing the connection back to the pool after each major stanza point with your monkeypatch fixed the issue.

  1. No trackbacks yet.