2
當在工作中對一些Clojure代碼進行壓力測試時,我發現在迭代大型數據集時,堆空間耗盡。我最終設法將這些問題追溯到Clojure的doseq
函數的組合,以及對懶惰序列的實現。doseq通過一個簡單的懶惰seq耗盡堆空間
這是最少的代碼片段,通過耗盡可用堆空間崩潰的Clojure:
(doseq [e (take 1000000000 (iterate inc 1))] (identity e))
爲doseq
的文件明確指出它不保留偷懶序列的頭,所以我期望上述代碼的內存複雜度接近O(1)。有什麼我失蹤?如果doseq
不能勝任這項工作,那麼循環遍歷極大的惰性序列的Clojure慣用方法是什麼?
Clojure的哪個版本和Java運行時您正在使用?在OSX上使用clojure 1.4/java 1.6.0_33在乾淨的repl中運行該代碼,顯示完全靜態內存使用率低於400 Mb – 2012-08-13 11:42:23
您確定這是導致問題的確切代碼段嗎?在我的機器上運行良好(Clojure 1.4,JDK7,Windows,Eclipse/CCW)。如果你以某種方式保持在序列的頭部,它將*成爲一個問題,例如,如果(iterate inc 1)存儲在其他地方。 – mikera 2012-08-14 02:13:56
你是對的,當我關閉Leiningen 2給REPL(歷史,關鍵導航等)添加的東西並且使用香草Clojure 1.4時,問題就消失了。謝謝。 – the80srobot 2012-08-14 08:07:13