-
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
Optimisations with Observable.empty() #1653
Comments
In this vein might be good to get |
This is inaccurate "I notice that calling observable.concat(Observable.empty()) invokes back-pressure". It was actually a combination of operators including concat. Regardless I think the optimisations would be useful. |
I stumbled upon your report while also looking at |
No idea why we aren't using |
Thanks @mttkay, that looks good. @benjchristensen what about more optimisations that would
For example,
but could be:
|
@davidmoten |
@davidmoten what about adding the empty check here, too: https://github.com/ReactiveX/RxJava/blob/1.x/src/main/java/rx/internal/operators/OperatorConcat.java#L126
|
there are a LOT of operators that can benefit from this. I would hazard a guess that most can use this optimisation at the high level within the |
If you want to submit a PR with this work done I'll accept it. If we can use |
Put on 1.0.x as this is not a blocker for 1.0, but whenever you submit the PR I'll do it. |
I'm starting work on this PR now and I'd like to get the ok on some detail. I'd propose adding this to private static final Observable<?> EMPTY = from(Collections.emptyList());
@SuppressWarnings("unchecked")
public final static <T> Observable<T> empty() {
return (Observable<T>) EMPTY;
} As an example of how it would be used the static method @SuppressWarnings("unchecked")
public final static <T> Observable<T> merge(Observable<? extends T> t1, Observable<? extends T> t2) {
if (t1 == EMPTY)
return (Observable<T>) t2;
else if (t2 == EMPTY)
return (Observable<T>) t1;
else
return merge(from(Arrays.asList(t1, t2)));
} Note that I've confirmed in the debugger that this optimisation avoids triggering backpressure if say A large number of methods will use this optimisation so I'd like to get my exact approach approved before submitting. The final thing to note is that optimisations outside of the @Override
public void onNext(Observable<? extends T> t) {
if(t==Observable.empty()) return; // check EMPTY
queue.add(nl.next(t));
if (WIP_UPDATER.getAndIncrement(this) == 0) {
subscribeNext();
}
} I'd like to limit the scope of my PR to optimisations in Observable.java only. Optimisations in Operators would wait for this base PR to be accepted. How does that sound? |
Why do you have so many Edit: At least I looked at the implementation and improved it in #2622. |
Ta for improvement. The reason I have o.flatMap(t -> {
if (cond(t))
return someObservable(t);
else
return Observable.empty();
}); I'm experimenting now with substituting the special case where the flatMap function returns either 0 or 1 by doing o.map(toOptional).filter(isPresent).map(toValue); I'd hope it would be faster but not sure. |
Yep I'll do benchmarks after those PRs have been merged. |
This may be part of the operator-fusion optimizations in 2.x but I don't see this in 1.x due to non-technical reasons. |
For a start: here is the baseline perf: #3754. I'm going to merge it so subsequent PRs can be benchmarked with it. |
See #3759 for the optimized |
See #3761 for the optimized |
Optimizations have been added and released with 1.1.4. Closing the issue. If you have more ideas where it's worth adding extra checks for empty, don't hesitate to open a new issue. |
I notice that calling
observable.concat(Observable.empty())
invokes back-pressure. I'd find it useful if when I usedObservable.empty()
that optimisations came into play such as ensuring thatobservable.concat(Observable.empty())
simply returnedobservable
.To achieve this I'd make a private constant
EMPTY = from(new ArrayList())
inObservable
so that callingObservable.empty()
always returned this object cast into the appropriate generic type. Then I'd use a simple object reference equality test to determine if an optimisation could be made.Do you think this proposal has legs? If so, I'll knock up a PR. I would seek to optimise more than just the
concat
operator , it would includemerge
and possibly others which I can think about if the time comes.The text was updated successfully, but these errors were encountered: