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

欢迎!请参阅关于页面以了解有关此内容的更多信息。

+1
Collections

从PersistentQueue中弹出的元素引用不会立即从队列中删除。这可能导致队列保留了比它当前包含的更多对象的情况。

这是因为在PersistentQueue中使用两个PersistentVectors实现,一个用于head,一个用于tail。一旦head为空,尾向量就会被转换为ChunkedSeq(通过在它上调用seq),然后放入head。然而,ChunkedSeq始终保留对整个起始向量的引用,即使它通过{{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"

;; 缩小此队列到仅剩一个元素
(nth (iterate pop (into q strs)) 99999)
=> ;; 一个元素队列

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

也许,如果这种行为是预期的,至少应该在文档中反映出来?鉴于PQ已经隐藏且未充分记录。

2 个回答

0

评论者为:alexeyakushev

编辑:将优先级更改为次要,因为这不是经典的内存泄漏(队列不会无限增长,最大的泄露大小为{{conj}} 在 {{pop}} 之前的最长连续串的大小)。

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