Как построение вычислений для больших задач сравнивается с одновременным выполнением нескольких шагов?
У меня есть следующие две части кода, написанные на Scala/Monix:
def f1(input) =
for {
a <- task1(input)
b <- task2(a)
c <- task3(b)
} yield (c).runSyncUnsafe
а также
def f2(input) = {
val a = task1(input).runSyncUnsafe
val b = task2(a).runSyncUnsafe
task3(b).runSyncUnsafe
}
Я думаю, что версия f1 лучше, поскольку она полностью асинхронна и не блокирует потоки, и я предполагаю, что, если выполняется много задач, первая должна работать лучше в многопоточности.
Я знаю, что должен написать тест для сравнения двух реализаций, но это потребовало бы большого количества рефакторинга унаследованного кода. Кроме того, профилирование двух версий не так просто в нашей конкретной ситуации, поэтому я сначала спрашиваю здесь, в надежде получить ответ от кого-то с большим опытом работы с Scala/Monix:
Как они должны сравниваться с точки зрения производительности при большой нагрузке? Это реальная проблема или это не проблема?
1 ответ
Как правило, лучше оставаться асинхронным как можно дольше. Чтобы ты мог написать f1
как это:
def f1(input) =
for {
a <- task1(input)
b <- task2(a)
c <- task3(b)
} yield c
После этого вызывающий абонент может решить, следует ли ему позвонить. runSyncUnsafe
или асинхронный вызов (runAsync
, runOnComplete
) или же flatMap
это с другой задачей. Это удаляет Unsafe
позвоните из своего кода и оставьте его вызывающему абоненту, чтобы решить, будет ли он в безопасности или нет.
Что касается производительности, то задачи будут оцениваться последовательно в любом случае, потому что более поздние задачи зависят от результатов более ранних задач.