gpt4 book ai didi

clojure - 如何在 Clojure 中忘记延迟序列的 head(GC'd)?

转载 作者:行者123 更新时间:2023-12-04 17:43:44 24 4
gpt4 key购买 nike

假设我有一个 巨大的 lazy seq 并且我想对其进行迭代,以便处理迭代期间获得的数据。

问题是我想 lost head(GC'd) of lazy seq (已处理),这样我就可以在没有 OutofMemoryException 的情况下处理具有数百万数据的序列。

我有 3 个我不确定的例子。

您能否为此目的提供 最佳实践(示例)

这些功能会失去理智吗?

示例 1

(defn lose-head-fn
[lazy-seq-coll]
(when (seq (take 1 lazy-seq-coll))
(do
;;do some processing...(take 10000 lazy-seq-coll)
(recur (drop 10000 lazy-seq-coll)))))

示例 2
(defn lose-head-fn
[lazy-seq-coll]
(loop [i lazy-seq-coll]
(when (seq (take 1 i))
(do
;;do some processing...(take 10000 i)
(recur (drop 10000 i))))))

示例 3
(doseq [i lazy-seq-coll]
;;do some processing...
)

更新: 这个答案中也有解释 here

最佳答案

通常,您必须 注意不要在本地或全局上为惰性序列的一部分保留引用,该引用位于另一个之前涉及过多计算的惰性序列 .

例如:

(let [nums (range)
first-ten (take 10 nums)]
(+ (last first-ten) (nth nums 100000000)))
=> 100000009

这在现代机器上大约需要 2 秒。不过这个怎么样?不同的是最后一行,其中 + 的参数顺序被交换:
;; Don't do this!
(let [nums (range)
first-ten (take 10 nums)]
(+ (nth nums 100000000) (last first-ten)))

如果您正在运行 htop,您会听到您的机箱/CPU 风扇栩栩如生。或类似的,您会看到内存使用量增长相当快(对我来说,前几秒钟大约 1G)。

这是怎么回事?

与链表非常相似,clojure 中惰性序列中的元素引用接下来出现的序列部分。在上面的第二个示例中, first-ten + 的第二个参数需要.因此,即使 nth很高兴不引用任何东西(毕竟,它只是在长列表中找到一个索引), first-ten指序列的一部分,如上所述,必须保留对序列其余部分的引用。

相比之下,第一个示例计算 (last first-ten) ,之后, first-ten不再使用。现在对惰性序列任何部分的唯一引用是 nums .如 nth完成它的工作,不再需要它完成的列表的每个部分, 并且由于没有其他内容涉及此 block 中的列表 ,如 nth遍历列表,已检查的序列占用的内存可以被垃圾收集。

考虑一下:
;; Don't do this!
(let [nums (range)]
(time (nth nums 1e8))
(time (nth nums 1e8)))

为什么这和上面的第二个例子有相似的结果?因为序列将在第一次实现时被缓存(保存在内存中)(第一个 (time (nth nums 1e8))), 因为在下一行使用了 nums .相反,如果我们对第二个 nth 使用不同的序列,则不需要缓存第一个,因此可以在处理时将其丢弃:
(let [nums (range)]
(time (nth nums 1e8))
(time (nth (range) 1e8)))
"Elapsed time: 2127.814253 msecs"
"Elapsed time: 2042.608043 msecs"

因此,当您使用大型惰性序列时,请考虑是否有任何东西仍然指向列表,如果有任何东西(全局变量是常见的),那么它 被铭记在心。

关于clojure - 如何在 Clojure 中忘记延迟序列的 head(GC'd)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44586291/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com