Does receive(on:)
have a performance limit?
Using ConcurrentDispatchQueue, as in the test code below, the sink is not fully called.
func testConcurrentDispatchQueueScheduler() {
// given
let concurrentQueue = DispatchQueue(label: "", qos: .default, attributes: .concurrent)
let lock = NSLock()
var count: Int = 0
var cancellables: Set<AnyCancellable> = []
// when
for _ in 0..<100 {
Just(Void())
.receive(on: concurrentQueue)
.sink { _ in
lock.lock(); defer { lock.unlock() } // make thread safely
count += 1
}
.store(in: &cancellables)
}
XCTWaiter().wait(for: [XCTestExpectation()], timeout: 1) // wait
// then
XCTAssertEqual(count, 100) // XCTAssertEqual failed: ("64") is not equal to ("100")
}
But, when use SerialDispatchQueue or queue.async { }
instead of receive(on:)
has not problem. (See below).
func testSerialDispatchQueueScheduler() {
// given
let serialQueue = DispatchQueue(label: "", qos: .default)
let lock = NSLock()
var count: Int = 0
var cancellables: Set<AnyCancellable> = []
// when
for _ in 0..<100 {
Just(Void())
.receive(on: serialQueue)
.sink { _ in
lock.lock(); defer { lock.unlock() } // make thread safely
count += 1
}
.store(in: &cancellables)
}
XCTWaiter().wait(for: [XCTestExpectation()], timeout: 1) // wait
// then
XCTAssertEqual(count, 100) // succeeded
}
func testConcurrentDispatchQueueAsync() {
// given
let concurrentQueue = DispatchQueue(label: "", qos: .default, attributes: .concurrent)
let lock = NSLock()
var count: Int = 0
var cancellables: Set<AnyCancellable> = []
// when
for _ in 0..<100 {
Just(Void())
.sink { _ in
concurrentQueue.async {
lock.lock(); defer { lock.unlock() } // make thread safely
count += 1
}
}
.store(in: &cancellables)
}
XCTWaiter().wait(for: [XCTestExpectation()], timeout: 1) // wait
// then
XCTAssertEqual(count, 100) // succeeded
}