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

ExecutorScheduler Concurrency and Performance Issues #713

Closed
benjchristensen opened this issue Jan 2, 2014 · 5 comments
Closed

ExecutorScheduler Concurrency and Performance Issues #713

benjchristensen opened this issue Jan 2, 2014 · 5 comments

Comments

@benjchristensen
Copy link
Member

The ExecutorScheduler, or at least the backing implementation of Schedulers.threadPoolForComputation() is needed because:

  1. It allows concurrent execution if used in a pattern other than sequential recursion. In other words, it doesn't protect against misuse: Fix Scheduler Memory Leaks #712 (comment)

  2. Performance is very bad when doing recursion: Recursion on ExecutorService with >1 Thread is Slow #711

benjchristensen added a commit to benjchristensen/RxJava that referenced this issue Jan 6, 2014
- simpler (no one remembers the current names when talking about them)
- does not tie naming to a particular implementation involving thread pools versus a pool of event loops or something similar (as we likely will change the implementation, see ReactiveX#713)
benjchristensen added a commit to benjchristensen/RxJava that referenced this issue Feb 7, 2014
See ReactiveX#713
It was causing non-deterministic behavior, random test failures and poor performance.
benjchristensen added a commit to benjchristensen/RxJava that referenced this issue Feb 9, 2014
See ReactiveX#713
It was causing non-deterministic behavior, random test failures and poor performance.
benjchristensen added a commit to benjchristensen/RxJava that referenced this issue Apr 19, 2014
@benjchristensen
Copy link
Member Author

Removed ExecutorScheduler and replaced with ComputationScheduler that has a pool of event loops: #1048

benjchristensen added a commit to benjchristensen/RxJava that referenced this issue Apr 20, 2014
@aij
Copy link

aij commented May 10, 2014

I seem to be failing to understand how ComputationScheduler is a replacement for ExecutorScheduler. I was using ExecutorScheduler because I needed certain code to run in a certain thread. Specifically, I was using .observeOn() so the observer would be executed on the Android main thread.

I'd also be perfectly happy with a scheduler that wraps a scala.concurrent.ExecutionContext instead, as that would be more idiomatic for Scala. Is there a way to do either with ComputationScheduler?

@samueltardieu
Copy link
Contributor

I used it to bound the number of IO requests in progress at the same time to avoid saturating the memory of the receiver on Android. I guess I will have to find another way.

@benjchristensen
Copy link
Member Author

I seem to be failing to understand how ComputationScheduler is a replacement for ExecutorScheduler

It's not a direct replacement. The ExecutorScheduler had significant problems as this issue discusses.

Specifically, I was using .observeOn() so the observer would be executed on the Android main thread.

You should use the AndroidScheduler: https://github.com/Netflix/RxJava/tree/master/rxjava-contrib/rxjava-android#observing-on-arbitrary-threads

as that would be more idiomatic for Scala

That should be done as part of rxjava-scala: https://github.com/Netflix/RxJava/tree/master/language-adaptors/rxjava-scala

I used it to bound the number of IO requests in progress at the same time

This is a valid use case (at Netflix we use Hystrix for that server-side, but that's not helpful for Android).

I'm totally okay with ExecutorScheduler coming back as long as it complies with the contract, which it never has. It is not obvious how to make it work.

The concurrent throttling case can be solved in other ways, including a Scheduler implementation that has a bounded number of threads, but that correctly use event loops on top of each thread. I know @akarnokd was experimenting with a fixed-side event loop pool that could be used for this.

If that was adopted into the core library, it would probably be something like Schedulers.fixedPool(int num), but the problem with that is it's a factory that produces a new pool every time, so users would have to make sure to create it and store a reference to it, otherwise it would not work. This is quite different from how the other Schedulers are used, where the factory methods are invoked every time such as Schedulers.io(), Schedulers.computation() and Schedulers.newThread().

What do you all think should be done?

@dvogel
Copy link

dvogel commented May 19, 2014

I would like to see the ExecutorScheduler come back without the default thread pool concurrency. ExecutorScheduler was the simplest way to delegate scheduling to the glib event loop:

public class GlibExecutor implements Executor {
    @Override
    public void execute(@NotNull final Runnable runnable) {
        Glib.idleAdd(new Handler() {
            public boolean run() {
                runnable.run();
                return false;
            }
        });
    }
}

It looks like I now have to subclass rx.Scheduler directly. That seems straight-forward enough, but the ExecutorScheduler was very nice here.

zsxwing pushed a commit to zsxwing/RxScala that referenced this issue Aug 19, 2014
benjchristensen added a commit to ReactiveX/RxJavaAsyncUtil that referenced this issue Aug 29, 2014
benjchristensen added a commit to ReactiveX/RxJavaComputationExpressions that referenced this issue Aug 29, 2014
jihoonson pushed a commit to jihoonson/RxJava that referenced this issue Mar 6, 2020
* fix resilience4j/resilience4j#712

* keep the 'which' as it is everywhere

* fix unit test
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants