From ba8d89c4c8d1c038c0d6fc9dbfe22f6d528d0da9 Mon Sep 17 00:00:00 2001 From: Carlhuda Date: Wed, 21 Jul 2010 16:29:26 -0700 Subject: Performance optimizations to handle cases of instrumentors that are not listened to. Also, fix a possible concurrency issue. --- activesupport/lib/active_support/notifications.rb | 24 ++++++++++++++++++++-- .../lib/active_support/notifications/fanout.rb | 11 +++++++--- .../active_support/notifications/instrumenter.rb | 2 +- 3 files changed, 31 insertions(+), 6 deletions(-) (limited to 'activesupport/lib') diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb index 93d1907edc..886d7183eb 100644 --- a/activesupport/lib/active_support/notifications.rb +++ b/activesupport/lib/active_support/notifications.rb @@ -41,10 +41,30 @@ module ActiveSupport autoload :Event, 'active_support/notifications/instrumenter' autoload :Fanout, 'active_support/notifications/fanout' + @instrumenters = Hash.new { |h,k| h[k] = notifier.listening?(k) } + class << self attr_writer :notifier - delegate :publish, :subscribe, :unsubscribe, :to => :notifier - delegate :instrument, :to => :instrumenter + delegate :publish, :unsubscribe, :to => :notifier + + def instrument(name, payload = {}) + if @instrumenters[name] + instrumenter.instrument(name, payload) { yield payload if block_given? } + else + yield payload if block_given? + end + end + + def subscribe(*args, &block) + notifier.subscribe(*args, &block).tap do + @instrumenters.clear + end + end + + def unsubscribe(*args) + notifier.unsubscribe(*args) + @instrumenters.clear + end def notifier @notifier ||= Fanout.new diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index 64f315cb6a..adc34f3286 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -9,15 +9,16 @@ module ActiveSupport end def subscribe(pattern = nil, block = Proc.new) - @listeners_for.clear - Subscriber.new(pattern, block).tap do |s| + subscriber = Subscriber.new(pattern, block).tap do |s| @subscribers << s end + @listeners_for.clear + subscriber end def unsubscribe(subscriber) - @listeners_for.clear @subscribers.reject! {|s| s.matches?(subscriber)} + @listeners_for.clear end def publish(name, *args) @@ -28,6 +29,10 @@ module ActiveSupport @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) } end + def listening?(name) + listeners_for(name).any? + end + # This is a sync queue, so there is not waiting. def wait end diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb index e98189f899..713d5a5f25 100644 --- a/activesupport/lib/active_support/notifications/instrumenter.rb +++ b/activesupport/lib/active_support/notifications/instrumenter.rb @@ -19,7 +19,7 @@ module ActiveSupport def instrument(name, payload={}) begin @started = Time.now - yield(payload) if block_given? + yield rescue Exception => e payload[:exception] = [e.class.name, e.message] raise e -- cgit v1.2.3