我在ST内部有一个计算,它通过Data.Vector.Unboxed.Mutable分配内存。永远不会读取或写入向量,也不会在runST之外保留任何引用(据我所知)。我遇到的问题是,当我多次运行ST计算时,我有时似乎会保留向量的内存。
分配统计:
5,435,386,768 bytes allocated in the heap
5,313,968 bytes copied during GC
134,364,780 bytes maximum residency (14 sample(s))
3,160,340 bytes maximum slop
518 MB total memory in use (0 MB lost due to fragmentation)
这里我用runST 20x调用不同的计算值和128MB向量(再次 - 未使用,未返回或在ST之外引用)。最大居住率看起来不错,基本上只是我的矢量加上几MB的其他东西。但总内存使用量表明我有四个同时激活的向量副本。这与矢量的大小完美匹配,对于256MB,我们可以按预期获得1030MB。
使用1GB向量耗尽内存(4x1GB +开销> 32位)。我不明白为什么RTS保持看似未使用的,未引用的内存而不仅仅是GC,至少在分配会失败的时候。
使用+ RTS -S运行会显示以下内容:
Alloc Copied Live GC GC TOT TOT Page Flts
bytes bytes bytes user elap user elap
134940616 13056 134353540 0.00 0.00 0.09 0.19 0 0 (Gen: 1)
583416 6756 134347504 0.00 0.00 0.09 0.19 0 0 (Gen: 0)
518020 17396 134349640 0.00 0.00 0.09 0.19 0 0 (Gen: 1)
521104 13032 134359988 0.00 0.00 0.09 0.19 0 0 (Gen: 0)
520972 1344 134360752 0.00 0.00 0.09 0.19 0 0 (Gen: 0)
521100 828 134360684 0.00 0.00 0.10 0.19 0 0 (Gen: 0)
520812 592 134360528 0.00 0.00 0.10 0.19 0 0 (Gen: 0)
520936 1344 134361324 0.00 0.00 0.10 0.19 0 0 (Gen: 0)
520788 1480 134361476 0.00 0.00 0.10 0.20 0 0 (Gen: 0)
134438548 5964 268673908 0.00 0.00 0.19 0.38 0 0 (Gen: 0)
586300 3084 268667168 0.00 0.00 0.19 0.38 0 0 (Gen: 0)
517840 952 268666340 0.00 0.00 0.19 0.38 0 0 (Gen: 0)
520920 544 268666164 0.00 0.00 0.19 0.38 0 0 (Gen: 0)
520780 428 268666048 0.00 0.00 0.19 0.38 0 0 (Gen: 0)
520820 2908 268668524 0.00 0.00 0.19 0.38 0 0 (Gen: 0)
520732 1788 268668636 0.00 0.00 0.19 0.39 0 0 (Gen: 0)
521076 564 268668492 0.00 0.00 0.19 0.39 0 0 (Gen: 0)
520532 712 268668640 0.00 0.00 0.19 0.39 0 0 (Gen: 0)
520764 956 268668884 0.00 0.00 0.19 0.39 0 0 (Gen: 0)
520816 420 268668348 0.00 0.00 0.20 0.39 0 0 (Gen: 0)
520948 1332 268669260 0.00 0.00 0.20 0.39 0 0 (Gen: 0)
520784 616 268668544 0.00 0.00 0.20 0.39 0 0 (Gen: 0)
521416 836 268668764 0.00 0.00 0.20 0.39 0 0 (Gen: 0)
520488 1240 268669168 0.00 0.00 0.20 0.40 0 0 (Gen: 0)
520824 1608 268669536 0.00 0.00 0.20 0.40 0 0 (Gen: 0)
520688 1276 268669204 0.00 0.00 0.20 0.40 0 0 (Gen: 0)
520252 1332 268669260 0.00 0.00 0.20 0.40 0 0 (Gen: 0)
520672 1000 268668928 0.00 0.00 0.20 0.40 0 0 (Gen: 0)
134553500 5640 402973292 0.00 0.00 0.29 0.58 0 0 (Gen: 0)
586776 2644 402966160 0.00 0.00 0.29 0.58 0 0 (Gen: 0)
518064 26784 134342772 0.00 0.00 0.29 0.58 0 0 (Gen: 1)
520828 3120 134343528 0.00 0.00 0.29 0.59 0 0 (Gen: 0)
521108 756 134342668 0.00 0.00 0.30 0.59 0 0 (Gen: 0)
这里似乎我们的“活字节数”超过了~128MB。
+RTS -hy
个人资料基本上只是说我们分配了128MB:
http://imageshack.us/a/img69/7765/45q8.png
我尝试在一个更简单的程序中重现这种行为,但即使用ST复制精确的设置,包含Vector的读者,相同的monad / program结构等,简单的测试程序也没有显示出来。简化我的大程序时,在删除看似完全不相关的代码时,行为也会最终停止。
Qs的:
+RTS -Hy
和maximum residency
声称我不是,我该怎么做才能阻止这种行为?谢谢!
答案 0 :(得分:2)
我怀疑这是GHC和/或RTS中的错误。
首先,我确信没有实际的空间泄漏或类似的东西。
原因:
现在,这是有趣的一点。如果我在每次运行函数后通过调用System.Mem.performGC
手动强制GC,问题就会完全消失。
所以我们有一个案例,运行时具有GB值的内存(可证明!)可以由GC回收,甚至根据自己的统计数据不再被任何人持有。当内存池耗尽时,运行时不会收集,而是要求操作系统获得更多内存。即使最终失败,运行时仍然不会收集(这可以回收GB的内存,但可以选择使用内存不足错误来终止程序。)
我不是Haskell,GHC或GC的专家。但这对我来说看起来确实很糟糕。我会将此报告为错误。