请在 2024 年 Clojure 状态调查! 中分享您的想法。

欢迎!有关更多信息,请参阅 关于 页面。

+1
集合

从 PersistentQueue 中弹出的元素引用不会立即从队列中移除。这可能导致队列保留的元素比当前包含的元素多得多。

这发生是因为 PersistentQueue 使用两个 PersistentVector 来实现,一个用于头部,一个用于尾部。一旦头部为空,尾部向量将被转换为 ChunkedSeq(通过调用 seq)并放入头部。然而,ChunkedSeq 总是保留对整个起始向量的引用,即使它在 shrunk 时被 next 缩小。

示例,使用 clj-memory-meter

`
(require '[clj-memory-meter.core :as mm])

(def q clojure.lang.PersistentQueue/EMPTY)
(def strs (repeatedly 100000 #(String. (.toCharArray "Hello"))))

;; 使用 100k 个 "Hello" 字符串的队列
(mm/measure (into q strs))
=> "5.9 MB"

;; 缩小此类队列以仅包含 1 个元素
(nth (iterate pop (into q strs)) 99999)
=> ;; 一个包含一个元素的队列

;; 但它仍然占用 6 MB
(mm/measure (nth (iterate pop (into q strs)) 99999))
=> "5.9 MB"
`

也许,如果这种行为是预期的,它至少可以在文档的某个地方反映出来?考虑到 PQ 已经是隐藏的并且文档不充分。

2 答案

0

评论由:alexyakushev 发布

编辑:将优先级更改为次要,因为这不是传统的内存泄漏(队列将不会无限增长,最大的泄漏是 conj 在 pop 之前的最大长度)。

0
参考: https://clojure.atlassian.net/browse/CLJ-2397(由 alexyakushev 报告)
...