ora*_*ock 1 memory performance clojure sequence lazy-evaluation
我是Clojure的新手.我有以下代码,它创建了一个无限懒惰的数字序列:
(defn generator [seed factor]
(drop 1 (reductions
(fn [acc _] (mod (* acc factor) 2147483647))
seed
; using dummy infinite seq to keep the reductions going
(repeat 1))))
Run Code Online (Sandbox Code Playgroud)
序列中的每个数字都取决于先前的计算.我正在使用,reductions因为我需要所有中间结果.
然后我实例化两个生成器,如下所示:
(def gen-a (generator 59 16807))
(def gen-b (generator 393 48271))
Run Code Online (Sandbox Code Playgroud)
然后我想比较n这些序列的连续结果,对于大n,并返回它们相等的次数.
起初我做了类似的事情:
(defn run []
(->> (interleave gen-a gen-b)
(partition 2)
(take 40000000)
(filter #(apply = %))
(count)))
Run Code Online (Sandbox Code Playgroud)
这花了太长时间,我看到该程序的内存使用量飙升至约4GB.有些printlns我看到它经过大约1000万次迭代后变得非常慢,所以我想可能count需要将整个序列存储在内存中,所以我把它更改为使用reduce:
(defn run-2 []
(reduce
(fn [acc [a b]]
(if (= a b)
(inc acc)
acc))
0
(take 40000000 (partition 2 (interleave gen-a gen-b)))))
Run Code Online (Sandbox Code Playgroud)
尽管如此,它还是分配了大量内存并在前几千万之后显着放缓.我很确定它将整个懒惰序列存储在内存中,但我不知道为什么,所以我试图手动扔掉头部:
(defn run-3 []
(loop [xs (take 40000000 (partition 2 (interleave gen-a gen-b)))
total 0]
(cond
(empty? xs) total
(apply = (first xs)) (recur (rest xs) (inc total))
:else (recur (rest xs) total))))
Run Code Online (Sandbox Code Playgroud)
同样,结果相同.这让我很难过,因为我读到我用来创建xs序列的所有函数都是懒惰的,因为我只使用当前项目,所以我期望它使用常量内存.
来自Python背景我基本上试图模拟Python生成器.我可能错过了一些明显的东西,所以我真的很感激一些指针.谢谢!
生成器不是(懒惰)序列.
你在这里坚持:
(def gen-a (generator 59 16807))
(def gen-b (generator 393 48271))
Run Code Online (Sandbox Code Playgroud)
gen-a并且gen-b是gobal vars指的是头部序列.
你可能想要这样的东西:
(defn run []
(->> (interleave (generator 59 16807) (generator 393 48271))
(partition 2)
(take 40000000)
(filter #(apply = %))
(count)))
Run Code Online (Sandbox Code Playgroud)
或者,定义gen-a和gen-b作为功能:
(defn gen-a
[]
(generator 59 16807)))
...
(defn run []
(->> (interleave (gen-a) (gen-b))
(partition 2)
(take 40000000)
(filter #(apply = %))
(count)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
218 次 |
| 最近记录: |