Skip to content

Commit

Permalink
Combine the two NIOAsyncChannel channel handlers
Browse files Browse the repository at this point in the history
Motivation:

The NIOAsyncChannel allocates 12 times on init. 4 of these allocations
come from creating two channel handlers and two channel handler
contexts. There's no inherent reason that these channel handlers can't
be combined to eliminate two allocations (one handler and one context).

Modifications:

- Combine `NIOAsyncChannelInboundStreamChannelHandler` and
  `NIOAsyncChannelOutboundWriterHandler` into a single
  `NIOAsyncChannelHandler`. Most of this was straightforward as only a
  few handler operations were duplicated across both.
- Add a 'NIOAsyncChannelHandlerWriterDelegate' in place of the
  'NIOAsyncChannelOutboundWriterHandler.Delegate'. One knock on from
  this is that the new delegate stores callbacks rather than the
  concrete type of the handler. This is necessary to prevent the
  generics from the new channel handler bubbling up to the outbound
  writer (which would break API and be somewhat odd).

Result:

Fewer allocations
  • Loading branch information
glbrntt committed Jul 10, 2024
1 parent 4d87167 commit 89b0877
Show file tree
Hide file tree
Showing 6 changed files with 282 additions and 374 deletions.
37 changes: 29 additions & 8 deletions Sources/NIOCore/AsyncChannel/AsyncChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -315,16 +315,27 @@ extension Channel {
) throws -> (NIOAsyncChannelInboundStream<Inbound>, NIOAsyncChannelOutboundWriter<Outbound>) {
self.eventLoop.assertInEventLoop()

let inboundStream = try NIOAsyncChannelInboundStream<Inbound>.makeWrappingHandler(
channel: self,
let handler = NIOAsyncChannelHandler<Inbound, Inbound, Outbound>(
eventLoop: self.eventLoop,
transformation: .syncWrapping { $0 },
isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled
)

let inboundStream = try NIOAsyncChannelInboundStream(
eventLoop: self.eventLoop,
handler: handler,
backPressureStrategy: backPressureStrategy,
closeOnDeinit: closeOnDeinit
)

let writer = try NIOAsyncChannelOutboundWriter<Outbound>(
channel: self,
eventLoop: self.eventLoop,
handler: handler,
isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled,
closeOnDeinit: closeOnDeinit
)

try self.pipeline.syncOperations.addHandler(handler)
return (inboundStream, writer)
}

Expand All @@ -338,17 +349,27 @@ extension Channel {
) throws -> (NIOAsyncChannelInboundStream<ChannelReadResult>, NIOAsyncChannelOutboundWriter<Never>) {
self.eventLoop.assertInEventLoop()

let inboundStream = try NIOAsyncChannelInboundStream<ChannelReadResult>.makeTransformationHandler(
channel: self,
let handler = NIOAsyncChannelHandler<Channel, ChannelReadResult, Never>(
eventLoop: self.eventLoop,
transformation: .transformation(channelReadTransformation: channelReadTransformation),
isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled
)

let inboundStream = try NIOAsyncChannelInboundStream(
eventLoop: self.eventLoop,
handler: handler,
backPressureStrategy: backPressureStrategy,
closeOnDeinit: closeOnDeinit,
channelReadTransformation: channelReadTransformation
closeOnDeinit: closeOnDeinit
)

let writer = try NIOAsyncChannelOutboundWriter<Never>(
channel: self,
eventLoop: self.eventLoop,
handler: handler,
isOutboundHalfClosureEnabled: isOutboundHalfClosureEnabled,
closeOnDeinit: closeOnDeinit
)

try self.pipeline.syncOperations.addHandler(handler)
return (inboundStream, writer)
}
}
Loading

0 comments on commit 89b0877

Please sign in to comment.