-
Notifications
You must be signed in to change notification settings - Fork 134
EventLoop preference overhaul #102
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
Conversation
|
CC @adtrevor |
| /// | ||
| /// In most cases you should use `currentEventLoop` instead | ||
| private var _currentEventLoop: EventLoop | ||
| /// The `EventLoop` the delegate will be executed on. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe there should also be a public accessible property to the channel's EventLoop?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would the use-case be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to add now or later if we feel there’s a compelling-enough reason
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about the backpressure futures of the delegate: performance wise, it's best to return one from the same event loop as the channel, which wouldn't be possible anymore if there is no access to the channel event loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm inclined to say that if that really matters much, the user should've chosen .delegateAndChannel(on: ...) and therefore the channel's EL == delegate's EL. @Lukasa what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it’s reasonable to be able to ask for the delegate loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Lukasa The delegate EventLoop should already be accessible with the eventLoop property, but I was thinking about the channel's EventLoop.
To give a more concrete example of what worries me, if you look at what happens in the ResponseAccumulator, the newest changes are doing this:
public func didReceiveHead(task: HTTPClient.Task<Response>, _: HTTPResponseHead) -> EventLoopFuture<Void> {
return task.eventLoop.makeSucceededFuture(())
}If no event loop preference is set, task.eventLoop can be completely different from the channel event loop.
But this means that in this part:
self.delegate.didReceiveBodyPart(task: self.task, body)
.hop(to: context.eventLoop)
The cost of hopping will be quite big especially something that's going to be called so much often.
It's true that for some uses .delegateAndChannel(on: ...) would probably be the best options, but for the delegates like ResponseAccumulator this isn't needed and yet being unable to access the channel el would loose performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand if letting public access to the channel event loop risks introducing too many errors on lib user side, maybe we could actually allow returning nil for the delegates that don't need backpressure? This would allow the client to choose the right event loop to get the best performance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I don't think it's worth exposing the channel event loop at this time. I understand the concern, and I think we can address it in the future, but for now I don't think I'd really bother. The performance concern is not really large enough (IMO) to justify it right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adtrevor if you really need that kind of performance, I'd say just use .delegateAndChannel(on: ...) and then the delegate and the Channel's EL are guaranteed to be the same. If we truly find that there are important use-cases to get the Channel's El we can, as Cory points out, add that at any point without breaking API.
|
@artemredkin I fixed the merge conflicts now. |
|
Do you want to merge of wait for @Lukasa's approval? |
Motivation:
With #96 we changed
HTTPClient.Task'seventLoopproperty to becurrentEventLoopbecause we anticipated that it might change because of the connection pool work that's ongoing.That however made the programming model rather hard because the user didn't get any guarantee anymore on which
EventLoopthe delegate would run.With this patch, we're bringing
eventLoopback which is theEventLoopthe delegate will run on. Note that it's not necessarily theEventLooptheChannelwill run on. If the user requires those to be the same, the can request that withEventLoopPreference.delegateAndChannel(on: eventLoop)rather than.indifferentor.delegate(on: eventLoop)Modification:
Let the user select between:
.indifferent: I don't care about theEventLoop.delegate(on: eventLoop): I want the delegate to be called oneventLoopand I would prefer theChannelto be oneventLooptoo but I'm happy if not.delegateAndChannel(on: eventLoop): I wantChanneland delegate to live oneventLoopResult: