Stop using method missing for singleton delegation.

This saved about 46 array allocations per request on an extremely simple
application.  The delegation happened in the notification subsystem
which is a hotspot, so this should result in even more savings with
larger apps.

Squashed commit of the following:

commit 41eef0d1479526f7de25fd4391d98e61c126d9f5
Author: Aaron Patterson <aaron.patterson@gmail.com>
Date:   Wed Nov 6 16:32:31 2013 -0800

    speed up notifications

commit 586b4a18656f66fb2c518fb8e8fee66a016e8ae6
Author: Aaron Patterson <aaron.patterson@gmail.com>
Date:   Wed Nov 6 16:31:05 2013 -0800

    speed up runtime registry methods

commit b67d074cb4314df9a88438f785868cef77e583d7
Author: Aaron Patterson <aaron.patterson@gmail.com>
Date:   Wed Nov 6 16:28:12 2013 -0800

    change method name and make it public
This commit is contained in:
Aaron Patterson 2013-11-06 16:32:47 -08:00
parent 4d15661d6c
commit 5584ddc43d
5 changed files with 15 additions and 9 deletions

View File

@ -13,5 +13,10 @@ module ActiveRecord
extend ActiveSupport::PerThreadRegistry extend ActiveSupport::PerThreadRegistry
attr_accessor :connection_handler, :sql_runtime, :connection_id attr_accessor :connection_handler, :sql_runtime, :connection_id
[:connection_handler, :sql_runtime, :connection_id].each do |val|
class_eval %{ def self.#{val}; instance.#{val}; end }, __FILE__, __LINE__
class_eval %{ def self.#{val}=(x); instance.#{val}=x; end }, __FILE__, __LINE__
end
end end
end end

View File

@ -23,6 +23,9 @@ module ActiveSupport
def set_cache_for(local_cache_key, value) def set_cache_for(local_cache_key, value)
@registry[local_cache_key] = value @registry[local_cache_key] = value
end end
def self.set_cache_for(l, v); instance.set_cache_for l, v; end
def self.cache_for(l); instance.cache_for l; end
end end
# Simple memory backed cache. This cache is not thread safe and is intended only # Simple memory backed cache. This cache is not thread safe and is intended only

View File

@ -178,7 +178,7 @@ module ActiveSupport
end end
def instrumenter def instrumenter
InstrumentationRegistry.instrumenter_for(notifier) InstrumentationRegistry.instance.instrumenter_for(notifier)
end end
end end

View File

@ -32,21 +32,19 @@ module ActiveSupport
# #
# If the class has an initializer, it must accept no arguments. # If the class has an initializer, it must accept no arguments.
module PerThreadRegistry module PerThreadRegistry
def instance
Thread.current[name] ||= new
end
protected protected
def method_missing(name, *args, &block) # :nodoc: def method_missing(name, *args, &block) # :nodoc:
# Caches the method definition as a singleton method of the receiver. # Caches the method definition as a singleton method of the receiver.
define_singleton_method(name) do |*a, &b| define_singleton_method(name) do |*a, &b|
per_thread_registry_instance.public_send(name, *a, &b) instance.public_send(name, *a, &b)
end end
send(name, *args, &block) send(name, *args, &block)
end end
private
def per_thread_registry_instance
Thread.current[name] ||= new
end
end end
end end

View File

@ -94,7 +94,7 @@ module ActiveSupport
private private
def event_stack def event_stack
SubscriberQueueRegistry.get_queue(@queue_key) SubscriberQueueRegistry.instance.get_queue(@queue_key)
end end
end end