Files
Dario Rexin e19c33affd [Concurrency] Improve performance of task groups
rdar://172192966

The tasks of a task group were stored in a singly linked list, causing a
linear scan for a task to find its predecessor, whenever a task completed
and had to be removed from the list. This change turns it into a doubly
linked list, so the linear scan is avoided completely.
2026-03-16 13:47:17 -07:00

65 lines
1.7 KiB
Swift

//===--- TaskGroup.swift --------------------------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2026 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
import TestsUtils
import Dispatch
public var benchmarks: [BenchmarkInfo] {
guard #available(macOS 14, iOS 17, tvOS 17, watchOS 10, *) else {
return []
}
return [
BenchmarkInfo(
name: "TaskGroups.1000",
runFunction: run_TaskGroup(groupSize: 1000),
tags: [.concurrency]
),
BenchmarkInfo(
name: "TaskGroups.5000",
runFunction: run_TaskGroup(groupSize: 5000),
tags: [.concurrency]
)
]
}
@available(macOS 14, iOS 17, tvOS 17, watchOS 10, *)
private func run_TaskGroup(groupSize: Int) -> (Int) -> Void {
return { n in
let g = DispatchGroup()
g.enter()
Task {
for _ in 0..<n {
var task: Task<Void, Never>! = nil
let cont: UnsafeContinuation<Void, Never> = await withUnsafeContinuation { cont in
task = Task {
await withUnsafeContinuation {
cont.resume(returning: $0)
}
}
}
await withDiscardingTaskGroup(returning: Void.self) { group in
for i in 0..<groupSize {
group.addTask {
await task.value
}
}
cont.resume()
}
}
g.leave()
}
g.wait()
}
}