I had a hunch that for highly computational, parallelized tasks in RxJava, a traditional ExecutorService
would be faster than a Scheduler
.
I had a theory that this code
Observable<MyItem> source = ...
source.flatMap(myItem -> myItem.process().subscribeOn(Schedulers.computation()))
.subscribe();
would run slower than this
final ExecutorService svc = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
Observable<MyItem> source = ...
source.flatMap(myItem -> myItem.process().subscribeOn(Schedulers.from(svc)))
.finallyDo(svc::shutdown)
.subscribe();
I compared these two approaches with a typical parallel process I do at work, and I got the following results.
EXECUTOR
START: 2016-01-25T09:47:04.350
END: 2016-01-25T09:48:37.181
TOTAL TIME (SEC): 92
COMPUTATION SCHEDULER
START: 2016-01-25T09:50:37.799
END: 2016-01-25T09:54:23.674
TOTAL TIME (SEC): 225
So my rough testing has shown the traditional ExecutorService
is much faster than a Scheduler
for computation.
Is there a reason for these results? Are RxJava schedulers just not optimized for parallelization? I've gotten the impression that computation schedulers use lesser threads than Executors.
Android Scheduler — This Scheduler is provided by rxAndroid library. This is used to bring back the execution to the main thread so that UI modification can be made. This is usually used in observeOn method.
ExecutorService abstracts away many of the complexities associated with the lower-level abstractions like raw Thread . It provides mechanisms for safely starting, closing down, submitting, executing, and blocking on the successful or abrupt termination of tasks (expressed as Runnable or Callable ).
Executor just executes stuff you give it. ExecutorService adds startup, shutdown, and the ability to wait for and look at the status of jobs you've submitted for execution on top of Executor (which it extends). This is a perfect answer, short and clear.
ExecutorService is a JDK API that simplifies running tasks in asynchronous mode. Generally speaking, ExecutorService automatically provides a pool of threads and an API for assigning tasks to it.
I did several tests and discovered that creating your own ExecutorService
can in fact increase parallelization performance. I wrote a blog post on it here.
When you use Schedulers.computation()
, all the events are handled in the same thread. You can refer to the source code CachedThreadScheduler.java
and NewThreadWorker.java
. The benefit of this implementation is that if eventA is emitted after eventB, then eventA will be handled after eventB.
When you use Schedulers.from()
, the events are handled in different threads.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With