Skip to content

Commit

Permalink
Reduce allocations on InlineStreamMultiplexer/createStreamChannel (#…
Browse files Browse the repository at this point in the history
…450)

## Motivation
When creating stream channels on the `InlineStreamMultiplexer`, we are currently performing a `flatSubmit` on two different codepaths. This allocates two ELFs: one on `submit`, and one on `flatMap`. This is unnecessary, as we could do with just one allocation.

## Modifications
Create a single ELP and call `execute` on the EL instead of using `flatSubmit`.

## Result
Fewer allocations
  • Loading branch information
gjcairo authored Jul 16, 2024
1 parent aab0f12 commit 79802e0
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 8 deletions.
17 changes: 13 additions & 4 deletions Sources/NIOHTTP2/HTTP2ChannelHandler+InlineStreamMultiplexer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,11 @@ extension InlineStreamMultiplexer {
self._commonStreamMultiplexer.createStreamChannel(multiplexer: .inline(self), streamStateInitializer)
}

@inlinable
internal func createStreamChannel<Output: Sendable>(promise: EventLoopPromise<Output>?, _ initializer: @escaping NIOChannelInitializerWithOutput<Output>) {
self._commonStreamMultiplexer.createStreamChannel(multiplexer: .inline(self), promise: promise, initializer)
}

@inlinable
internal func createStreamChannel<Output: Sendable>(_ initializer: @escaping NIOChannelInitializerWithOutput<Output>) -> EventLoopFuture<Output> {
self._commonStreamMultiplexer.createStreamChannel(multiplexer: .inline(self), initializer)
Expand Down Expand Up @@ -284,19 +289,23 @@ extension InlineStreamMultiplexer {
// Always create streams channels on the next event loop tick. This avoids re-entrancy
// issues where handlers interposed between the two HTTP/2 handlers could create streams
// in channel active which become activated twice.
return self._eventLoop.flatSubmit {
self._inlineStreamMultiplexer.createStreamChannel(initializer)
let promise: EventLoopPromise<Channel> = self._eventLoop.makePromise()
self._eventLoop.execute {
self._inlineStreamMultiplexer.createStreamChannel(promise: promise, initializer)
}
return promise.futureResult
}

@inlinable
internal func createStreamChannel<Output: Sendable>(_ initializer: @escaping NIOChannelInitializerWithOutput<Output>) -> EventLoopFuture<Output> {
// Always create streams channels on the next event loop tick. This avoids re-entrancy
// issues where handlers interposed between the two HTTP/2 handlers could create streams
// in channel active which become activated twice.
return self._eventLoop.flatSubmit {
self._inlineStreamMultiplexer.createStreamChannel(initializer)
let promise: EventLoopPromise<Output> = self._eventLoop.makePromise()
self._eventLoop.execute {
self._inlineStreamMultiplexer.createStreamChannel(promise: promise, initializer)
}
return promise.futureResult
}

internal func setChannelContinuation(_ streamChannels: any AnyContinuation) {
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.2204.510.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ services:
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=889050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=44050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace=200050
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.2204.58.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ services:
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=889050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=44050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace=200050
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.2204.59.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ services:
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=889050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=44050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace=200050
Expand Down
2 changes: 1 addition & 1 deletion docker/docker-compose.2204.main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ services:
- MAX_ALLOCS_ALLOWED_client_server_request_response_many_inline=889050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=44050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_inline_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_create_client_stream_channel_no_promise_based_API=37050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form=200050
- MAX_ALLOCS_ALLOWED_get_100000_headers_canonical_form_trimming_whitespace=200050
Expand Down

0 comments on commit 79802e0

Please sign in to comment.