Pet*_*lák 37 profiling haskell memory-leaks ghc
我正在研究接收和处理JSON请求的Haskell守护程序.虽然守护进程的操作很复杂,但主要结构有意保持简单:它的内部状态只是IORef一个数据结构,所有线程都对此执行原子操作IORef.然后有几个线程在触发器上取值时用它做一些事情.
问题是守护进程泄漏了内存,我无法找到原因.它肯定与请求相关:当守护进程每秒收到多个请求时,它会泄漏大小为1MB/s(由Linux工具报告).内存消耗稳步增长.没有请求,内存消耗保持不变.
令我感到困惑的是,这些都没有在GHC分析中显示出来.要么我在配置文件参数中缺少某些内容,要么内存被其他内容消耗:
运行+RTS -hc -xt -p:

运行+RTS -hr -xt -p:

在此测试运行期间,守护程序随后消耗超过1GB.因此,分析数据显然与实际消耗的内存数量级不对应.(我知道RTS,GC和性能分析本身会增加实际内存消耗,但这种差异太大了,并不符合不断增加的消耗.)
我已经尝试rnf了守护进程内的所有状态数据IORef,以及解析的JSON请求(以避免部分JSON字符串保留在某处),但没有太大的成功.
欢迎任何想法或建议.
更新:守护程序没有运行-threaded,因此没有操作系统级别的线程.
GC统计信息更接近堆分析而不是Linux报告的数字:
Alloc Copied Live GC GC TOT TOT Page Flts
bytes bytes bytes user elap user elap
[...]
5476616 44504 2505736 0.00 0.00 23.21 410.03 0 0 (Gen: 0)
35499296 41624 2603032 0.00 0.00 23.26 410.25 0 0 (Gen: 0)
51841800 46848 2701592 0.00 0.00 23.32 410.49 0 0 (Gen: 0)
31259144 36416 2612088 0.00 0.00 23.40 410.61 0 0 (Gen: 0)
53433632 51976 2742664 0.00 0.00 23.49 412.05 0 0 (Gen: 0)
48142768 50928 2784744 0.00 0.00 23.54 412.49 0 0 (Gen: 0)
[...]
Run Code Online (Sandbox Code Playgroud)
更新2:我发现了问题的根源,内存泄漏是造成handleToFd(见这个问题对于UNIX库).我只是想知道如何更有效地查明这样的泄漏(可能发生在外国代码中).
小智 2
虽然我不熟悉 Haskell 守护进程本身,但回答你的问题“如何更有效地查明此类泄漏”,也许可以使用
valgrind --leak-check=yes haskelldaemon(如果使用调试信息编译它会更好),
或者,如果泄漏发生在共享库中,请尝试
LD_PRELOAD="yourlibrary.so" valgrind your-executable。