Ответ 1
Я сделал несколько тестов и обнаружил, что создание собственного ExecutorService
может фактически увеличить производительность параллелизации. Я написал здесь сообщение в блоге.
У меня была догадка, что для высоко вычислительных, параллельных задач в RxJava традиционный ExecutorService
будет быстрее, чем Scheduler
.
У меня была теория, что этот код
Observable<MyItem> source = ...
source.flatMap(myItem -> myItem.process().subscribeOn(Schedulers.computation()))
.subscribe();
будет работать медленнее, чем этот
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();
Я сравнил эти два подхода с типичным параллельным процессом, который я делаю на работе, и получил следующие результаты.
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
Итак, мое грубое тестирование показало, что традиционный ExecutorService
намного быстрее, чем Scheduler
для вычисления.
Есть ли причина для этих результатов? Планировщики RxJava просто не оптимизированы для распараллеливания? У меня сложилось впечатление, что планировщики вычислений используют меньше потоков, чем Executors.
Я сделал несколько тестов и обнаружил, что создание собственного ExecutorService
может фактически увеличить производительность параллелизации. Я написал здесь сообщение в блоге.
Когда вы используете Schedulers.computation()
, все события обрабатываются в одном потоке. Вы можете обратиться к исходному коду CachedThreadScheduler.java
и NewThreadWorker.java
. Преимущество этой реализации состоит в том, что если eventA выдается после события B, то eventA будет обрабатываться после событияB.
Когда вы используете Schedulers.from()
, события обрабатываются в разных потоках.