Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add no-op NIOHTTP2ConnectionDemultiplexer #377

Conversation

rnro
Copy link
Contributor

@rnro rnro commented Mar 3, 2023

Motivation:

This change prepares for future work to embed the connection demultiplexer within the HTTP2ChannelHandler which will improve performance by removing the need for passing expensive InboundUserEvents.

Modifications:

This first step defines a new protocol (NIOHTTP2ConnectionDemultiplexer) which will later be used to abstract over the embedded and legacy separate demultiplexer code but at the moment should not change the logic.

Result:

Behaviour should be unchanged.

@@ -272,6 +278,7 @@ public final class NIOHTTP2Handler: ChannelDuplexHandler {
// This is the easy one. We were active, now we aren't.
self.activationState = .inactive
self.channelClosed = true
self.demultiplexer = nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit aggressive: we don't need to throw this away right now.


/// Wraps user event types.
///
/// This allows us to buffer and pass around the events without making use of a generic.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strictly this was an existential.


func pendingUserEvent(_ event: Any) {
func pendingUserEvent(_ event: BufferedHTTP2UserEvent) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To reduce the noise of this patch somewhat, it might be nicer to add individual pendingUserEvent functions for each of the types in the enum cases, and then the call sites don't have to change.

self.demultiplexer?.streamWindowUpdated(event.streamID, inboundWindowSize: event.inboundWindowSize, outboundWindowSize: event.outboundWindowSize)
case .streamClosed(let event):
self.demultiplexer?.streamClosed(event.streamID, reason: event.reason)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we hide this switch in an extension on the demultiplexer? It'll again let us clean up this call site somewhat.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have moved this to:

extension NIOHTTP2Handler.ConnectionDemultiplexer {
    func process(event: InboundEventBuffer.BufferedHTTP2UserEvent) {

rnro added 2 commits March 3, 2023 13:55
Motivation:

This change prepares for future work to embed the connection demultiplexer within the `HTTP2ChannelHandler` which will improve performance by removing the need for passing expensive `InboundUserEvent`s.

Modifications:

This first step defines a new protocol (`NIOHTTP2ConnectionDemultiplexer`) which will later be used to abstract over the embedded and legacy separate demultiplexer code but at the moment should not change the logic.

Result:

Behaviour should be unchanged.
* no longer `nil` out demultiplexer on channelInactive
* restructure calling `pendingUserEvent` & processing events
@rnro rnro force-pushed the add_demultiplexer_protocol_abstraction_to_NIOHTTP2Handler branch from 74741be to bfe93ce Compare March 3, 2023 13:55
@rnro rnro requested a review from Lukasa March 3, 2023 14:36
@Lukasa Lukasa added the semver/patch No public API change. label Mar 6, 2023
self.inboundEventBuffer.pendingUserEvent(
NIOHTTP2StreamCreatedEvent(streamID: streamCreatedData.streamID,
localInitialWindowSize: streamCreatedData.localStreamWindowSize.map(UInt32.init),
remoteInitialWindowSize: streamCreatedData.remoteStreamWindowSize.map(UInt32.init)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you clean up the indentation here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I have done this now. I have certainly changed it.

case .streamWindowUpdated(let event):
self.streamWindowUpdated(event.streamID, inboundWindowSize: event.inboundWindowSize, outboundWindowSize: event.outboundWindowSize)
case .streamClosed(let event):
self.streamClosed(event.streamID, reason: event.reason)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing it like this makes me ask the question: is there a good reason these functions aren't defined to simply take the event directly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I sketched out the API I didn't consider what was already there (i.e. the inbound event buffer). So no, no good reason to not use events directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to use the events directly.

NIOHTTP2ConnectionDemultiplexer stream  events now use event types
directly rather than individual parameters which map to the event
fields.
@rnro rnro requested a review from Lukasa March 6, 2023 10:59
@Lukasa Lukasa enabled auto-merge (squash) March 6, 2023 11:04
@Lukasa Lukasa merged commit 20d0634 into apple:main Mar 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
semver/patch No public API change.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants