From 1d3897c6bff58fcc329af0de2615c62ac158f651 Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Thu, 1 Oct 2026 13:08:33 -0400 Subject: [PATCH 1/2] Dispatch immediate tasks without a work item `DefaultScheduler.runImmediate` wrapped every task in a `DispatchWorkItem`, which allocates the work item and copies the task's block a second time. Every `NetworkContext.async` goes through it, which includes the hop that delivers each inbound datagram and the cleanup a stream schedules when it is torn down. The work item was only there because its initializer accepts a non-`Sendable` closure; the task is now handed to the queue directly, just as unchecked. Each task costs two allocations instead of four. Measured on my Mac against `main` with the package's QUIC benchmark tools. Allocation counts come from full malloc stack logging, which records every allocation: QUICTransfer -size 1200, per message 24.37 -> 22.14 QUICTransfer, per 500 KB transfer 6,187.6 -> 6,131.8 QUICHandshake, per connection 1,947.4 -> 1,941.5 QUICStreamLoad, per stream 111.8 -> 106.9 Wall-clock time comes from running `main`, this change and the other changes measured alongside it in a rotating order for 9 rounds, and comparing each run with `main`'s in the same round. Changes moved paths they do not touch by up to about 1.3%, so differences that size count as noise. The stream load took 1.4% less time, faster in 7 of 9 rounds; the transfers and the handshakes did not change beyond noise. --- Sources/SwiftNetwork/Context/NetworkContext.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Sources/SwiftNetwork/Context/NetworkContext.swift b/Sources/SwiftNetwork/Context/NetworkContext.swift index 3bf8b64..6a549cd 100644 --- a/Sources/SwiftNetwork/Context/NetworkContext.swift +++ b/Sources/SwiftNetwork/Context/NetworkContext.swift @@ -372,7 +372,11 @@ extension NetworkContext { /// Runs an immediate task. This task must not be run directly on the caller's stack, but otherwise /// no assumptions are made about how the task is run. func runImmediate(_ task: @escaping (() -> Void)) { - globals.queue.async(execute: DispatchWorkItem(block: task)) + // Tasks are not `Sendable`; the queue is what serializes them, so the task is handed over + // unchecked. Wrapping it in a `DispatchWorkItem` would skip the check too, but costs a work + // item and a second block copy on every task. + nonisolated(unsafe) let task = task + globals.queue.async { task() } } /// Schedules a task to run after a delay, using a reference. func schedule(_ task: @escaping (() -> Void), after delay: NetworkDuration, reference: TimerReference) { From 5cea86ea3a13a9f9ba7ac961e2889642e6e54c5a Mon Sep 17 00:00:00 2001 From: Rick Newton-Rogers Date: Fri, 2 Oct 2026 10:07:55 -0400 Subject: [PATCH 2/2] Hand immediate tasks to the queue in an `@unchecked Sendable` wrapper `runImmediate` marked its task `nonisolated(unsafe)` so that it could reach the queue without a `Sendable` check. That modifier speaks of actor isolation in code with no actor, and the reason the hand-over is safe lived only in a comment. `QueuedTask` states it as a conformance instead, the same way `NetworkContext` declares its own `@unchecked Sendable`. The allocation count is unchanged. --- Sources/SwiftNetwork/Context/NetworkContext.swift | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Sources/SwiftNetwork/Context/NetworkContext.swift b/Sources/SwiftNetwork/Context/NetworkContext.swift index 6a549cd..1f2316b 100644 --- a/Sources/SwiftNetwork/Context/NetworkContext.swift +++ b/Sources/SwiftNetwork/Context/NetworkContext.swift @@ -369,14 +369,18 @@ extension NetworkContext { init(globals: Globals) { self.globals = globals } + /// A task for the context's queue to run. + /// + /// Tasks are not `Sendable`; the queue serializes them, which is the guarantee `NetworkContext` rests on + /// for its own `@unchecked Sendable` conformance. + private struct QueuedTask: @unchecked Sendable { + let run: () -> Void + } /// Runs an immediate task. This task must not be run directly on the caller's stack, but otherwise /// no assumptions are made about how the task is run. func runImmediate(_ task: @escaping (() -> Void)) { - // Tasks are not `Sendable`; the queue is what serializes them, so the task is handed over - // unchecked. Wrapping it in a `DispatchWorkItem` would skip the check too, but costs a work - // item and a second block copy on every task. - nonisolated(unsafe) let task = task - globals.queue.async { task() } + let queued = QueuedTask(run: task) + globals.queue.async { queued.run() } } /// Schedules a task to run after a delay, using a reference. func schedule(_ task: @escaping (() -> Void), after delay: NetworkDuration, reference: TimerReference) {