При стресс-тестировании некоторого кода Clojure на работе я заметил, что ему не хватает места в куче при переборе больших наборов данных. В конце концов мне удалось отследить проблемы до комбинации функции Clojure doseq
и реализации ленивых последовательностей.
Это минимальный фрагмент кода, который приводит к сбою Clojure из-за исчерпания доступного места в куче:
(doseq [e (take 1000000000 (iterate inc 1))] (identity e))
В документации для doseq
четко указано, что он не сохраняет заголовок ленивой последовательности, поэтому я ожидаю, что сложность памяти в приведенном выше коде будет близка к O (1). Есть что-то, что мне не хватает? Что за Clojure-идиоматический способ перебора чрезвычайно больших ленивых последовательностей, если doseq
не подходит?