Это будет иметь некоторые накладные расходы. Если вы пытаетесь получить time
разницы в миллисекундах, это немного искажает вещи (хотя в любом случае минутные интервалы не следует использовать time
).
Я думаю, что ваш пример был немного запутанным, поэтому я сократил его до того, что, по моему мнению, представляет проблему немного лучше:
(time (doseq [n (range 5)]
(future
(Thread/sleep 2000))))
"Elapsed time: 1.687702 msecs"
Проблема здесь та же, что и с вашим кодом: все, что действительно нужно, это время, которое требуется doseq
для отправки всех заданий.
Идея моего взлома состоит в том, чтобы поместить каждое законченное задание в атом, а затем проверить состояние завершения в состоянии ожидания:
(defn do-stuff [n-things]
(let [ret-atom (atom 0)]
(doseq [n (range n-things)]
(future
(Thread/sleep 2000)
(swap! ret-atom inc)))
ret-atom))
; Time how long it takes the entire `let` to run
(time
(let [n 5
ret-atom (do-stuff n)]
; Will block until the condition is met
(while (< @ret-atom n))))
"Elapsed time: 2002.813288 msecs"
Причина, по которой это так сложно для времени, заключается в том, что все, что вы делаете, - это ускорение побочных эффектов в doseq
. Нет ничего, что определяло бы то, что «сделано», поэтому нечего блокировать. Я не очень хорошо разбираюсь в core.async
, но подозреваю, что там может что-то помочь. Может быть возможно иметь вызов к <!!
, который блокирует, пока канал не имеет определенного количества элементов. В этом случае вам просто нужно поместить результаты в канал по мере их появления.