diff --git a/Receiver/Sources/Receiver.swift b/Receiver/Sources/Receiver.swift index 5877afc..4e6c455 100644 --- a/Receiver/Sources/Receiver.swift +++ b/Receiver/Sources/Receiver.swift @@ -68,7 +68,8 @@ public class Receiver { private let values = Atomic<[Wave]>([]) private let strategy: Strategy - private let handlers = Atomic<[Int:Handler]>([:]) + private let handlers = Atomic<[UInt64:Handler]>([:]) + private var nextKey: UInt64 = 0 private init(strategy: Strategy) { self.strategy = strategy @@ -105,12 +106,12 @@ public class Receiver { /// a new value is sent. /// - returns: A reference to a disposable @discardableResult public func listen(to handle: @escaping (Wave) -> Void) -> Disposable { - var _key: Int! - handlers.apply { _handlers in - _key = (_handlers.keys.map { $0.hashValue }.max() ?? -1) + 1 - _handlers[_key] = handle - } - + var _key: UInt64! + handlers.apply { _handlers in + _key = nextKey + _handlers[_key] = handle + nextKey = nextKey &+ 1 + } switch strategy { case .cold: broadcast(elements: Int.max) diff --git a/ReceiverTests/ReceiverTests+Performance.swift b/ReceiverTests/ReceiverTests+Performance.swift index b807fb4..89235e3 100644 --- a/ReceiverTests/ReceiverTests+Performance.swift +++ b/ReceiverTests/ReceiverTests+Performance.swift @@ -18,4 +18,37 @@ class ReceiverTests_Performance: XCTestCase { } } } + + func test_listen_and_dispose_performance() { + self.measure { + let numberOfListeners = 10000 + var numberOfDisposes = 0 + let (transmitter, receiver) = Receiver.make() + var called = 0 + var disposables = [Disposable]() + + for i in 1...numberOfListeners { + + let disposable = receiver.listen { wave in + XCTAssertTrue(wave == 1) + called = called + 1 + } + + disposables.append(disposable) + + if i % 3 == 0 && disposables.count > 0 { + let d = disposables.remove(at: Int.random(in: 0..