-
Notifications
You must be signed in to change notification settings - Fork 7.6k
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
Operator Publish full rewrite #2814
Operator Publish full rewrite #2814
Conversation
Wow. Will have to come back to this one :-) that's a pretty epic fix of my bad code! |
@davidmoten have you by chance tried this and been able to confirm it fixes your issues? |
Ah, it was easy; you only need to dualize merge :). |
@benjchristensen the original issue is covered by the rewrite, thanks @akarnokd . I've given the code a once over but not thorough, would take me a while and have little time at the moment. |
@akarnokd I have had another brief foray into the code and I have every faith in your ability to create correct code but I'm not having a great time following it in the short slots of time I have between kid juggling. For longevity's sake I'm wondering if this beautiful looking bit of code could be bulked up with comments to lead me through and to lead future maintainers through. Of course if @benjchristensen or @zsxwing or another of the usual suspects think it's clear as day then further comments may be unnecessary. |
Sure. |
97173da
to
ccec09c
Compare
I've rebased, squashed and added comments to this PR. |
In |
ccec09c
to
d9588ff
Compare
Thanks! Updated tests accordingly and fixed a case with clients starting with 0 requests. |
Perhaps add a |
d9588ff
to
a9f041b
Compare
Done. |
// Now find the minimum amount each child-subscriber requested | ||
// since we can only emit that much to all of them without violating | ||
// backpressure constraints | ||
for (InnerProducer<T> ip : ps) { |
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.
This is one strategy I suppose and another might be request max but buffer responses for those subscribers that want less than max. I can imagine that either way somebody could suffer and I wonder if this strategy should be configurable?
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.
You can only request the common minimum amount from upstream if the front-queue is bounded, even if some child subscribers request more. These may run ahead but then stay idle until the 'slower ones' catch up.
By the way thanks for the comments in the code, they are just what I need! |
I'm preparing a JMH benchmark and it seems the current master fails with MissingBackpressureException on simple chains such as: @Test
public void testObserveOn() {
ConnectableObservable<Integer> co = Observable.range(0, 1000).publish();
Observable<Integer> obs = co.observeOn(Schedulers.computation());
for (int i = 0; i < 100; i++) {
TestSubscriber<Integer> ts = new TestSubscriber<Integer>();
obs.subscribe(ts);
Subscription s = co.connect();
ts.awaitTerminalEvent(2, TimeUnit.SECONDS);
ts.assertTerminalEvent();
ts.assertNoErrors();
assertEquals(1000, ts.getOnNextEvents().size());
s.unsubscribe();
}
} I'll post and merge the PR for the perf test so it can be run independent of this PR. |
a9f041b
to
bf12d32
Compare
I'll post its benchmark result but it takes a looong time. So far, I'm impressed (sync, 1 batch, 1 child, 1M elements): |
Here is the benchmark result for this PR in JMH Comparison GUI format. This PR outperforms the current master by 1.5 - 4x most of the time. However, some async parameter combination timed out despite the high CPU usage; I'll look into those cases. Edit: |
*/ | ||
continue; | ||
/* | ||
* Note: although technically corrent, concurrent disconnects can cause |
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.
By concurrent disconnect, I assume you mean concurrent subscribe/disconnect? If so then yes, the child subscribers may never receive anything if it is not re-connected. But that is exactly correct behavior if that's what happens.
Am I understanding your comment here correctly?
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.
Yes, the behavior implemented and what you said is the correct one.
Excellent code. Excellent comments. Very well done @akarnokd. This is a very hard piece of code. I can only imagine how much time you spent on this. As best as I can tell it's all correct. It's complicated enough I may be missing something, but everything seems correct and matches what I wish I had coded this to be originally! |
Operator Publish full rewrite
Complete rewrite of
publish()
and fixed bugs of #2810 and #2803.