From 206b7c712d08723010d74cc2322c1a0c47472c3c Mon Sep 17 00:00:00 2001 From: George Barnett Date: Thu, 2 Jul 2026 10:40:46 +0100 Subject: [PATCH] Avoid allocating in FrameArray empty init `FrameArray()` sets the minimum capacity to one which allocates a backing storage. This is a foot gun which is already triggered on many code paths: an empty `FrameArray()` is initialized only to be assigned over shortly after, resulting in an avoidable temporary allocation. This pattern is avoidable but takes care, however a simpler solution which removes the foot gun altogether is to not request capacity in `FrameArray()`. When capacity is known users should use `FrameArray(capacity:)` instead. This change reduces allocations by ~7% and CPU cycles by ~5% in the QUIC benchmarks I ran. --- Sources/SwiftNetwork/Protocols/FrameArray.swift | 2 +- Sources/SwiftNetwork/QUIC/QUICConnection.swift | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/Sources/SwiftNetwork/Protocols/FrameArray.swift b/Sources/SwiftNetwork/Protocols/FrameArray.swift index 5bbb353..90e59cd 100644 --- a/Sources/SwiftNetwork/Protocols/FrameArray.swift +++ b/Sources/SwiftNetwork/Protocols/FrameArray.swift @@ -36,7 +36,7 @@ public struct FrameArray: ~Copyable { } public init() { - self.frames = NetworkUniqueDeque(minimumCapacity: 1) + self.frames = NetworkUniqueDeque() } public init(capacity: Int) { diff --git a/Sources/SwiftNetwork/QUIC/QUICConnection.swift b/Sources/SwiftNetwork/QUIC/QUICConnection.swift index 8ff817c..557315d 100644 --- a/Sources/SwiftNetwork/QUIC/QUICConnection.swift +++ b/Sources/SwiftNetwork/QUIC/QUICConnection.swift @@ -3196,11 +3196,14 @@ public final class QUICConnection: ManyToManyApplicationStreamProtocol, else { return false } - var datagramBatch = FrameArray() + + var datagramBatch: FrameArray if self.flowControlState.pendingOutboundBytesToSend > 0 && availableCongestionWindow > 0 { datagramBatch = buildOutboundFrameBatch( availableCongestionWindow: (availableCongestionWindow - totalSendBytes) ) + } else { + datagramBatch = FrameArray() } // Sending on the current path.