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

欢迎!请查看关于页面以获取更多关于如何使用本站的信息。

+8
core.async
以下代码将导致 OOME


(require '[clojure.core.async :refer [chan close! <! pub sub unsub go timeout]])

(def p* (chan))

(def p (pub p* :topic))

(go
  (loop []
    (let [s (chan)
          odat (rand-int Integer/MAX_VALUE)]
      (sub p t s)
      (<! (timeout 10))
      (unsub p t s)
      (close! s)
      (recur))))


(It grows slowly: to see the OOME in a reasonable amount of time, either give JVM very small
memory like 64m, or remove the timeout step.)

I tried to profile the code, and the reason seems to be that even though I
unsubed the channel from the port, something is still retained which causes
the heap to be used up.

6 答案

0

评论者:amadeoh

这里的问题是

https://github.com/clojure/core.async/blob/96de9a47ac511d9bb4309645a3bc594a2fc0c33a/src/main/clojure/clojure/core/async.clj#L826-L828

当调用 unsub* 时,它只是从由主题指定的多路复用通道取消订阅。即使多路复用没有取消订阅,它仍然保留在多路复用通道的原子中。

由于当前将多路复用通道连接到多路复用的通道没有被公开,即我们目前没有方法知道多路复用是否有任何取消订阅,因此我无法想出一个简单的解决方案来解决这个问题。

0

评论者:gshayban

出于同样的原因,我也无法找到一个干净的解决方案,因为多路复用不公开它们的注册者。("当前"的并发系统概念是微妙的。)
除了声明(可能修改文档字符串)发布者确实是资源外,它们的足迹会随着看到的主题数量的1.增长,而且资源几乎总是应该有边界的。

0

评论由 [email protected] 提出

这个问题也影响了 https://github.com/apa512/clj-rethinkdb/issues/97。我建议增加的文档字符串如下

发布者是资源,并且它们的足迹随着看到的主题数量增长。未发布的未回收这些资源。你不应该使用发布者订阅无边界数量的主题。

有任何更改/建议吗?您希望我为这个创建补丁吗?

0

评论由 [email protected] 提出

此外,当发布者不再使用时,它是否能被垃圾回收?在我进行一些有限的测试时,它似乎不能,但我可能错了。

0

评论由 [email protected] 提出

一个部分解决方案(我认为?)是使用
`(unsub-all pub topic)`
如果你知道不再需要这个主题。

0
参考:https://clojure.atlassian.net/browse/ASYNC-90(由 alex+import 报告)
...