Skip to content

Commit 596e994

Browse files
committed
Add testConcurrencyThreadPoolWidth
1 parent 1358a77 commit 596e994

File tree

1 file changed

+61
-0
lines changed

1 file changed

+61
-0
lines changed

Tests/NIOCoreTests/AsyncSequences/NIOAsyncWriterTests.swift

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -710,6 +710,67 @@ final class NIOAsyncWriterTests: XCTestCase {
710710

711711
self.assert(suspendCallCount: 0, yieldCallCount: 0, terminateCallCount: 1)
712712
}
713+
714+
func testConcurrencyThreadPoolWidth() async {
715+
let finished = expectation(description: "finished")
716+
Thread {
717+
var tasks: [(Task<Void, Never>, ConditionLock<Bool>)] = []
718+
var initialNumberOfThreads = 0
719+
720+
// Start tasks and block them.
721+
// Each task is given some time to start. If it takes too long, the thread pool has reached its maximum width.
722+
for i in 0..<256 {
723+
let taskStarted = ConditionLock(value: false)
724+
let taskBlocker = ConditionLock(value: false)
725+
726+
print("\(Date.now): Starting Task \(i)")
727+
fflush(stdout)
728+
let startTime = ContinuousClock.now
729+
let task = Task {
730+
print("\(Date.now): Task \(i) started")
731+
fflush(stdout)
732+
733+
// Indicate that the task has started
734+
taskStarted.lock()
735+
taskStarted.unlock(withValue: true)
736+
737+
// Block
738+
taskBlocker.lock(whenValue: true)
739+
taskBlocker.unlock()
740+
}
741+
tasks.append((task, taskBlocker))
742+
743+
if taskStarted.lock(whenValue: true, timeoutSeconds: 10) {
744+
taskStarted.unlock()
745+
if startTime.duration(to: .now) < .seconds(0.5) {
746+
// If the task started very quickly, a thread was already available.
747+
initialNumberOfThreads = i + 1
748+
}
749+
} else {
750+
print("Detected initial number of threads: \(initialNumberOfThreads)")
751+
print("Detected maximum number of threads: \(i)")
752+
fflush(stdout)
753+
break
754+
}
755+
}
756+
757+
// Unblock all tasks
758+
for (_, taskBlocker) in tasks {
759+
taskBlocker.lock()
760+
taskBlocker.unlock(withValue: true)
761+
}
762+
763+
// Wait for all tasks to finish
764+
Task {
765+
for (task, _) in tasks {
766+
await task.value
767+
}
768+
finished.fulfill()
769+
}
770+
}.start()
771+
772+
await fulfillment(of: [finished], timeout: 600)
773+
}
713774
}
714775

715776
#if !canImport(Darwin) && swift(<5.9.2)

0 commit comments

Comments
 (0)