diff options
author | Aaron Patterson <tenderlove@github.com> | 2019-02-01 13:36:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-01 13:36:25 -0800 |
commit | 2ccbddb48c96b0cda9641961541d7266591a3db7 (patch) | |
tree | 9fa638fcf39ee2a69ea5d99d8678391ff57e968e | |
parent | caf8dbc1591c64ae4fd9253a714903710f46f7ce (diff) | |
parent | 211222cc182218c06e9a1b094f48d9e96e905865 (diff) | |
download | rails-2ccbddb48c96b0cda9641961541d7266591a3db7.tar.gz rails-2ccbddb48c96b0cda9641961541d7266591a3db7.tar.bz2 rails-2ccbddb48c96b0cda9641961541d7266591a3db7.zip |
Merge pull request #35133 from jhawthorn/faster_notifications
Make Notifications::Fanout faster after changing subscriptions
-rw-r--r-- | activesupport/lib/active_support/notifications/fanout.rb | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/activesupport/lib/active_support/notifications/fanout.rb b/activesupport/lib/active_support/notifications/fanout.rb index 4e4ca70942..11721db103 100644 --- a/activesupport/lib/active_support/notifications/fanout.rb +++ b/activesupport/lib/active_support/notifications/fanout.rb @@ -13,7 +13,8 @@ module ActiveSupport include Mutex_m def initialize - @subscribers = [] + @string_subscribers = Hash.new { |h, k| h[k] = [] } + @other_subscribers = [] @listeners_for = Concurrent::Map.new super end @@ -21,8 +22,13 @@ module ActiveSupport def subscribe(pattern = nil, block = Proc.new) subscriber = Subscribers.new pattern, block synchronize do - @subscribers << subscriber - @listeners_for.clear + if String === pattern + @string_subscribers[pattern] << subscriber + @listeners_for.delete(pattern) + else + @other_subscribers << subscriber + @listeners_for.clear + end end subscriber end @@ -31,12 +37,18 @@ module ActiveSupport synchronize do case subscriber_or_name when String - @subscribers.reject! { |s| s.matches?(subscriber_or_name) } + @string_subscribers[subscriber_or_name].clear + @listeners_for.delete(subscriber_or_name) else - @subscribers.delete(subscriber_or_name) + pattern = subscriber_or_name.try(:pattern) + if String === pattern + @string_subscribers[pattern].delete(subscriber_or_name) + @listeners_for.delete(pattern) + else + @other_subscribers.delete(subscriber_or_name) + @listeners_for.clear + end end - - @listeners_for.clear end end @@ -56,7 +68,8 @@ module ActiveSupport # this is correctly done double-checked locking (Concurrent::Map's lookups have volatile semantics) @listeners_for[name] || synchronize do # use synchronisation when accessing @subscribers - @listeners_for[name] ||= @subscribers.select { |s| s.subscribed_to?(name) } + @listeners_for[name] ||= + @string_subscribers[name] + @other_subscribers.select { |s| s.subscribed_to?(name) } end end @@ -101,6 +114,8 @@ module ActiveSupport end class Evented #:nodoc: + attr_reader :pattern + def initialize(pattern, delegate) @pattern = pattern @delegate = delegate |