Фактически, doall
отлично работает. Единственная проблема с вашим примером - медленная функция iterate
. Вы должны использовать range вместо него:
(doall (range 5000000000 5005000000))
range
очень быстро. Это лениво, но он оптимизирован и генерирует числа в кусках.
Вот результаты тестов для iterate
и run
, полученные с помощью criterium:
user=> (quick-bench (doall (take 5000 (iterate inc 5000000))))
Evaluation count : 180 in 6 samples of 30 calls.
Execution time mean : 3.175749 ms
Execution time std-deviation : 1.179449 ms
Execution time lower quantile : 2.428681 ms (2.5%)
Execution time upper quantile : 4.735748 ms (97.5%)
Overhead used : 14.758153 ns
user=> (quick-bench (doall (range 5000000 5005000)))
Evaluation count : 672 in 6 samples of 112 calls.
Execution time mean : 1.253228 ms
Execution time std-deviation : 350.301594 µs
Execution time lower quantile : 845.026223 µs (2.5%)
Execution time upper quantile : 1.582950 ms (97.5%)
Overhead used : 14.758153 ns
Как вы можете видеть, range
в 2,5 раза быстрее, чем iterate
здесь.
На моем компьютере требуется меньше секунды, чтобы сгенерировать все 5000000 номеров, но есть некоторые трюки, чтобы заставить его работать еще быстрее.
Например, вы можете запустить генерацию в отдельном потоке:
(let [numbers (range 5000000000 5005000000)]
(future (dorun numbers))
...)
Он не будет делать поколение быстрее, но вы будете иметь возможность немедленно использовать последовательность, прежде чем она будет полностью -realized.
Вам нужен быстрый способ заполнения медленной структуры данных? –
Вы можете указать начало и конец (и шаг) с помощью 'range'. –
@AlisterLee: быстрый способ не быстрый. Я знал, что мой подход не был самым быстрым подходом к заполнению списка – artella