-
Notifications
You must be signed in to change notification settings - Fork 117
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
EventLoop preference overhaul #102
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
'seventLoop
property to becurrentEventLoop
because 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
EventLoop
the delegate would run.With this patch, we're bringing
eventLoop
back which is theEventLoop
the delegate will run on. Note that it's not necessarily theEventLoop
theChannel
will run on. If the user requires those to be the same, the can request that withEventLoopPreference.delegateAndChannel(on: eventLoop)
rather than.indifferent
or.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 oneventLoop
and I would prefer theChannel
to be oneventLoop
too but I'm happy if not.delegateAndChannel(on: eventLoop)
: I wantChannel
and delegate to live oneventLoop
Result: