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

Pass multiplexer from ConnectionManager rather than channel #1062

Merged
merged 17 commits into from
Dec 9, 2020

Conversation

PeterAdams-A
Copy link
Contributor

Motivation:

The multiplexer is what's actually required and is expensive to
look up from the channel.

Modifications:

Pass the multiplexor through the Idle Handler and the ConnectionManager
to the requester.

Update tests to match.

Result:

Approximately 3% faster on unary calls.

Motivation:

The multiplexer is what's actually required and is expensive to
look up from the channel.

Modifications:

Pass the multiplexor through the Idle Handler and the ConnectionManager
to the requester.

Update tests to match.

Result:

Approximately 3% faster on unary calls.
channel = state.readyChannelPromise.futureResult
switch self.state {
case .idle:
self.startConnecting()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it be easier for startConnecting to just return the future you want?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably not as in getHTTP2MultiplexerOptimistic the one you want is different. I guess the logic could be pushed in but then the decision point wouldn't match for the other cases.

Copy link
Collaborator

@glbrntt glbrntt left a comment

Choose a reason for hiding this comment

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

I have a small thread safety concern and a few nits but this generally looks good.

internal struct IdleState {
var configuration: ClientConnection.Configuration
}
internal struct IdleState {}
Copy link
Collaborator

Choose a reason for hiding this comment

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

May as well delete this type instead.

Sources/GRPC/ConnectionManager.swift Show resolved Hide resolved
}

/// Returns a future for the current channel, or future channel from the current connection
/// Returns a future for the current channel multiplexer, or future channel multiplexer from the current connection
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: let's call it an HTTP/2 stream multiplexer rather than a channel multiplexer

Comment on lines 341 to 344
// Unexpected to get here.
self.invalidState()
case .connecting:
// Unexpected to get here.
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: add a comment saying why.


case let .active(state):
channel = state.candidate.eventLoop.makeSucceededFuture(state.candidate)
case .active:
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: might as well collapse the remaining states: case .active, .ready, .transientFailure, .shutdown:

Comment on lines 513 to 515
self
.state =
.active(ConnectedState(from: connecting, candidate: channel, multiplexer: multiplexer))
Copy link
Collaborator

Choose a reason for hiding this comment

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

swiftformat makes some real beauties sometimes... can we have something like the following instead:

let connected = ConnectedState(from: ...)
self.state = .active(connected)

channel: channel,
inboundStreamInitializer: nil
)
_ = channel.pipeline.addHandler(
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: try and wait()

@PeterAdams-A PeterAdams-A requested a review from glbrntt December 2, 2020 17:52
@PeterAdams-A
Copy link
Contributor Author

I believe I've fixed all your comments George.

@PeterAdams-A
Copy link
Contributor Author

@glbrntt Notice the sneaky extra commit.

@glbrntt
Copy link
Collaborator

glbrntt commented Dec 3, 2020

@PeterAdams-A you're hitting an invalid state:

Test Case 'GRPCClientKeepaliveTests.testKeepaliveTimeoutFiresBeforeConnectionIsReady' started at 2020-12-03 08:33:59.119
Fatal error: Invalid state connecting(GRPC.ConnectionManager.ConnectingState(backoffIterator: Optional(GRPC.ConnectionBackoffIterator), reconnect: GRPC.ConnectionManager.Reconnect.after(1.0), candidate: NIO.EventLoopFuture<NIO.Channel>, readyChannelMuxPromise: NIO.EventLoopPromise<NIOHTTP2.HTTP2StreamMultiplexer>(futureResult: NIO.EventLoopFuture<NIOHTTP2.HTTP2StreamMultiplexer>))) for fulfillMuxPromiseGivenState(promise:): file /home/travis/build/grpc/grpc-swift/Sources/GRPC/ConnectionManager.swift, line 355

promise.fail(state.reason)
}
}

return self.eventLoop.flatSubmit {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since getHTTP2Multiplexer ensures we're on the event loop we no longer need to submit the work to it

Comment on lines 382 to 383
connecting.candidate
.whenComplete { _ in fulfillMuxPromiseGivenState(promise: muxPromise) }
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure if this is correct: the channel future can complete before we receive channel active, i.e. we can still be in the connecting state when fulfilling the promise.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This turned out to be quite a big change involving adding an extra promise to state.

@PeterAdams-A PeterAdams-A requested a review from glbrntt December 3, 2020 16:48
Copy link
Collaborator

@glbrntt glbrntt left a comment

Choose a reason for hiding this comment

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

This looks good to me, thanks @PeterAdams-A! I added a couple of suggestions to fix pre-existing typos.

Sources/GRPC/ConnectionManager.swift Outdated Show resolved Hide resolved
Sources/GRPC/ConnectionManager.swift Outdated Show resolved Hide resolved
@glbrntt glbrntt added the 🔨 semver/patch No public API change. label Dec 8, 2020
@glbrntt glbrntt merged commit 548411e into grpc:main Dec 9, 2020
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