Skip to content

Commit

Permalink
Reduce error allocations (#446)
Browse files Browse the repository at this point in the history
Motivation:

Existential errors are unconditionally boxed. We typically create and
use errors to fail promises when performing cleanup work. One example
of this is failing pending writes when a stream channel is closed,
however this is done unconditionally which means every stream channel
incurs an allocation when it closes.

Modifications:

- Statically create some existential errors ahead of time

Result:

Fewer allocations
  • Loading branch information
glbrntt authored Jul 5, 2024
1 parent d629013 commit ed8a315
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 40 deletions.
22 changes: 22 additions & 0 deletions Sources/NIOHTTP2/Error+Any.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2024 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

import NIOCore

// 'any Error' is unconditionally boxed, avoid allocating per use by statically boxing them.
extension ChannelError {
static let _alreadyClosed: any Error = ChannelError.alreadyClosed
static let _eof: any Error = ChannelError.eof
static let _ioOnClosedChannel: any Error = ChannelError.ioOnClosedChannel
}
8 changes: 4 additions & 4 deletions Sources/NIOHTTP2/HTTP2StreamChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ final class HTTP2StreamChannel: Channel, ChannelCore, @unchecked Sendable {

public func write0(_ data: NIOAny, promise userPromise: EventLoopPromise<Void>?) {
guard self.state != .closed else {
userPromise?.fail(ChannelError.ioOnClosedChannel)
userPromise?.fail(ChannelError._ioOnClosedChannel)
return
}

Expand Down Expand Up @@ -584,7 +584,7 @@ final class HTTP2StreamChannel: Channel, ChannelCore, @unchecked Sendable {
// If the stream is already closed, we can fail this early and abort processing. If it's not, we need to emit a
// RST_STREAM frame.
guard self.state != .closed else {
promise?.fail(ChannelError.alreadyClosed)
promise?.fail(ChannelError._alreadyClosed)
return
}

Expand Down Expand Up @@ -643,7 +643,7 @@ final class HTTP2StreamChannel: Channel, ChannelCore, @unchecked Sendable {
}
self.modifyingState { $0.completeClosing() }
self.dropPendingReads()
self.failPendingWrites(error: ChannelError.eof)
self.failPendingWrites(error: ChannelError._eof)
if let promise = self.pendingClosePromise {
self.pendingClosePromise = nil
promise.succeed(())
Expand Down Expand Up @@ -842,7 +842,7 @@ internal extension HTTP2StreamChannel {
/// - promise: The promise associated with the frame write.
private func receiveOutboundFrame(_ frame: HTTP2Frame, promise: EventLoopPromise<Void>?) {
guard self.state != .closed else {
let error = ChannelError.alreadyClosed
let error = ChannelError._alreadyClosed
promise?.fail(error)
self.errorEncountered(error: error)
return
Expand Down
24 changes: 12 additions & 12 deletions docker/docker-compose.2204.510.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ services:
test:
image: swift-nio-http2:22.04-5.10
environment:
- MAX_ALLOCS_ALLOWED_1k_requests_inline_interleaved=35150
- MAX_ALLOCS_ALLOWED_1k_requests_inline_noninterleaved=34100
- MAX_ALLOCS_ALLOWED_1k_requests_interleaved=41150
- MAX_ALLOCS_ALLOWED_1k_requests_noninterleaved=40100
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response=288050
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response_inline=273050
- MAX_ALLOCS_ALLOWED_client_server_request_response=257050
- MAX_ALLOCS_ALLOWED_client_server_request_response_inline=248050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many=1202050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=893050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=39050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=39050
- MAX_ALLOCS_ALLOWED_1k_requests_inline_interleaved=34150
- MAX_ALLOCS_ALLOWED_1k_requests_inline_noninterleaved=33100
- MAX_ALLOCS_ALLOWED_1k_requests_interleaved=40150
- MAX_ALLOCS_ALLOWED_1k_requests_noninterleaved=39100
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response=286050
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response_inline=271050
- MAX_ALLOCS_ALLOWED_client_server_request_response=255050
- MAX_ALLOCS_ALLOWED_client_server_request_response_inline=246050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many=1200050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=891050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=38050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=38050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace_from_long_string=300050
Expand Down
24 changes: 12 additions & 12 deletions docker/docker-compose.2204.58.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ services:
test:
image: swift-nio-http2:22.04-5.8
environment:
- MAX_ALLOCS_ALLOWED_1k_requests_inline_interleaved=35150
- MAX_ALLOCS_ALLOWED_1k_requests_inline_noninterleaved=34100
- MAX_ALLOCS_ALLOWED_1k_requests_interleaved=41150
- MAX_ALLOCS_ALLOWED_1k_requests_noninterleaved=40100
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response=288050
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response_inline=273050
- MAX_ALLOCS_ALLOWED_client_server_request_response=257050
- MAX_ALLOCS_ALLOWED_client_server_request_response_inline=248050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many=1202050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=893050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=39050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=39050
- MAX_ALLOCS_ALLOWED_1k_requests_inline_interleaved=34150
- MAX_ALLOCS_ALLOWED_1k_requests_inline_noninterleaved=33100
- MAX_ALLOCS_ALLOWED_1k_requests_interleaved=40150
- MAX_ALLOCS_ALLOWED_1k_requests_noninterleaved=39100
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response=286050
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response_inline=271050
- MAX_ALLOCS_ALLOWED_client_server_request_response=255050
- MAX_ALLOCS_ALLOWED_client_server_request_response_inline=246050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many=1200050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=891050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=38050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=38050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace_from_long_string=300050
Expand Down
24 changes: 12 additions & 12 deletions docker/docker-compose.2204.59.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ services:
test:
image: swift-nio-http2:22.04-5.9
environment:
- MAX_ALLOCS_ALLOWED_1k_requests_inline_interleaved=35150
- MAX_ALLOCS_ALLOWED_1k_requests_inline_noninterleaved=34100
- MAX_ALLOCS_ALLOWED_1k_requests_interleaved=41150
- MAX_ALLOCS_ALLOWED_1k_requests_noninterleaved=40100
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response=288050
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response_inline=273050
- MAX_ALLOCS_ALLOWED_client_server_request_response=257050
- MAX_ALLOCS_ALLOWED_client_server_request_response_inline=248050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many=1202050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=893050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=39050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=39050
- MAX_ALLOCS_ALLOWED_1k_requests_inline_interleaved=34150
- MAX_ALLOCS_ALLOWED_1k_requests_inline_noninterleaved=33100
- MAX_ALLOCS_ALLOWED_1k_requests_interleaved=40150
- MAX_ALLOCS_ALLOWED_1k_requests_noninterleaved=39100
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response=286050
- MAX_ALLOCS_ALLOWED_client_server_h1_request_response_inline=271050
- MAX_ALLOCS_ALLOWED_client_server_request_response=255050
- MAX_ALLOCS_ALLOWED_client_server_request_response_inline=246050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many=1200050
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=891050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=38050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=38050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace_from_long_string=300050
Expand Down

0 comments on commit ed8a315

Please sign in to comment.