我有以下功能:
(defn- clock-process [every f]
(while true
(f)
(Thread/sleep every)))
我正在将它旋转到自己的线程中,以避免阻塞主线程:
(future
(clock-process 3600000 ;; fire every hour
#(intensive-fn ...)))
在Heroku dyno上,每小时间隔的总内存使用量大幅增长:
内存中断的地方是应用程序重新启动的地方。
有谁能帮我理解发生了什么?
答案 0 :(得分:1)
我不知道足以帮助您理解为什么会发生这种情况,但我可以建议一些方法来缓解这个问题。
tl; dr:降低堆大小可能是最好的选择。
首先,设置Memory logging agent。这会定期将一些消息打印到日志中,如:
source=web.1 measure.mem.jvm.heap.used=33M measure.mem.jvm.heap.committed=376M measure.mem.jvm.heap.max=376M
source=web.1 measure.mem.jvm.nonheap.used=19M measure.mem.jvm.nonheap.committed=23M measure.mem.jvm.nonheap.max=219M
source=web.1 measure.threads.jvm.total=21 measure.threads.jvm.daemon=11 measure.threads.jvm.nondaemon=1 measure.threads.jvm.internal=9
由此,您将能够确定增长发生的位置(即堆或非堆)。
如果您发现增长都是堆,则应尝试设置最大堆大小(即-Xmx
)。低于默认值。像-Xmx300m
这样的东西应该足够了,但你可能会降低。您还可以生成一些堆转储,并使用Eclipse MAT之类的工具对其进行分析,如果您想要查明来源。
如果您发现增长是在非堆中,那么请使用troubleshooting guide中描述的其他一些步骤来确定它是否是Metaspace或其他内容。如果它不在Metaspace中,那么您可能会有本机内存泄漏,这可能是由于保留文件句柄或缓冲区而导致的。
您是否尝试过在本地重现此问题?如果你这样做,使用像VisualVM和jmap
这样的工具更容易深入挖掘。
最后,您可以打开support ticket with Heroku。他们可以查看smaps
之类的内容来帮助解决非堆/本机内存泄漏问题。