首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么下面的代码有通道子/不明嫌犯的内存泄漏?

为什么下面的代码有通道子/不明嫌犯的内存泄漏?
EN

Stack Overflow用户
提问于 2020-07-22 09:05:12
回答 1查看 534关注 0票数 4

我正在使用[org.clojure/clojure "1.10.1"],[org.clojure/core.async "1.2.603"]和最新的AmazonCorretto11JVM,如果与它们有任何关系的话。

下面的代码是生产中使用的代码的简化版本,它确实会导致内存泄漏。我不知道为什么会这样,但我怀疑这可能是因为频道的分/不明。有人能帮我指出我的代码哪里出错,或者我如何修复内存泄漏吗?

代码语言:javascript
复制
(ns test-gc.core
  (:require [clojure.core.async :as a :refer [chan put! close! <! go >! go-loop timeout]])
  (:import [java.util UUID]))

(def global-msg-ch (chan (a/sliding-buffer 200)))

(def global-msg-pub (a/pub global-msg-ch :id))

(defn io-promise []
  (let [id (UUID/randomUUID)
        ch (chan)]
    (a/sub global-msg-pub id ch)
    [id (go
          (let [x (<! ch)]
            (a/unsub global-msg-pub id ch)
            (:data x)))]))

(defn -main []
  (go-loop []
    (<! (timeout 1))
    (let [[pid pch] (io-promise)
          cmd {:id   pid
               :data (rand-int 1E5)}]
      (>! global-msg-ch cmd)
      (println (<! pch)))
    (recur))
  (while true
    (Thread/yield)))

快速堆转储提供了以下统计信息,例如:

按实例数划分的

代码语言:javascript
复制
- `java.util.LinkedList`                        5,157,128 (14.4%)
- `java.util.concurrent.atomic.AtomicReference` 3,698,382 (10.3%)
- `clojure.lang.Atom`                           3,094,279 (8.6%)
- ...

按实例大小划分的

代码语言:javascript
复制
- `java.lang.Object[]`    210,061,752 B (13.8%)
- `java.util.LinkedList`  206,285,120 B (13.6%)
- `clojure.lang.Atom`     148,525,392 B (9.8%)
- `clojure.core.async.impl.channels.ManyToManyChannel` 132,022,336 B (8.7%)
- ...
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-07-30 09:18:10

我终于弄明白了原因。通过查看源代码,我们得到了以下部分:

代码语言:javascript
复制
(defn pub
  "Creates and returns a pub(lication) of the supplied channel, ..."
  ...
     (let [mults (atom {}) ;;topic->mult
           ensure-mult (fn [topic]
                         (or (get @mults topic)
                             (get (swap! mults
                                         #(if (% topic) % (assoc % topic (mult (chan (buf-fn topic))))))
                                  topic)))
           p (reify
              Mux
              (muxch* [_] ch)

              Pub
              (sub* [p topic ch close?]
                    (let [m (ensure-mult topic)]
                      (tap m ch close?)))
              (unsub* [p topic ch]
                      (when-let [m (get @mults topic)]
                        (untap m ch)))
              (unsub-all* [_] (reset! mults {}))
              (unsub-all* [_ topic] (swap! mults dissoc topic)))]
       ...
       p)))

我们可以看到mults存储的所有topic,因此,如果我们不清除它将单调增加。我们可以添加像(a/unsub-all* global-msg-pub pid)这样的东西来解决这个问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63030659

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档