Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #11111 (closed enhancement: fixed)

Opened 5 months ago

Last modified 5 months ago

[PATCH] Improve attributes_with_quotes method performance by doing less calls to AR::Base::connection

Reported by: adymo Assigned to: core
Priority: normal Milestone: 2.x
Component: ActiveRecord Version: edge
Severity: normal Keywords:
Cc:

Description

AR does too many calls to AR::Base#connection method. Especially that's true for quoting attributes and attribute columns. It's more efficient to get connection object once and then call its methods directly.

This patch changes both #attributes_with_quotes and #quoted_column_names methods to do that.

The effect is of course visible for operations with many calls to AR#save. In my case that saved about 50ms when creating 100 AR objects.

Attachments

less_connection_method_calls.patch (1.2 kB) - added by adymo on 02/13/08 20:25:28.

Change History

02/13/08 20:25:28 changed by adymo

  • attachment less_connection_method_calls.patch added.

(follow-up: ↓ 2 ) 02/14/08 00:02:06 changed by jamesh

I'm a bit confused by this patch. For example:

       def attributes_with_quotes(include_primary_key = true, include_readonly_attributes = true)
         quoted = {}
+        connection = self.class.connection
         @attributes.each_pair do |name, value|
           if column = column_for_attribute(name)
-            quoted[name] = quote_value(read_attribute(name), column) unless !include_primary_key && column.primary
+            quoted[name] = connection.quote(read_attribute(name), column) unless !include_primary_key && column.primary
           end
         end

Your changes effectively take out the refactored 'quote_value' and replace it with a call to an instance variable with your connection. Wouldn't it just be wiser to cache the connection in 'quote_value'?

Perhaps something more like:

def quote_value(value, column = nil) #:nodoc:
  @quote_value_connection ||= connection.quote(value,column)
end

(in reply to: ↑ 1 ) 02/14/08 00:04:02 changed by jamesh

Oops! I buggered my suggestion. This instead:

def quote_value(value, column = nil) #:nodoc:
  @quote_value_connection ||= connection
  @quote_value_connection.quote(value,column)
end

02/14/08 04:51:36 changed by blj

connection is already cached in AR::Base no?

02/14/08 07:47:09 changed by adymo

Yes, it is cached already in @@active_connections class var. But to get it with AR::Base.class#connection, we need extra 2 method calls (one for #connection itself and another for #active_connections). Method calls are not cheap in Ruby (10000 calls cost ~2.7ms on my machine) and if the AR model has many attributes and Rails app is calling #create or #save in a loop, we get significant slowdown just because of those 2 method calls.

02/14/08 20:09:09 changed by nzkoz

  • status changed from new to closed.
  • resolution set to fixed.

(In [8871]) Avoid repeated calls to Base#connection. Closes #11111 [adymo]