Подтвердить что ты не робот

RxJava - Планировщики против 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.

4b9b3361

Ответ 1

Я сделал несколько тестов и обнаружил, что создание собственного ExecutorService может фактически увеличить производительность параллелизации. Я написал здесь сообщение в блоге.

Ответ 2

Когда вы используете Schedulers.computation(), все события обрабатываются в одном потоке. Вы можете обратиться к исходному коду CachedThreadScheduler.java и NewThreadWorker.java. Преимущество этой реализации состоит в том, что если eventA выдается после события B, то eventA будет обрабатываться после событияB.

Когда вы используете Schedulers.from(), события обрабатываются в разных потоках.