内存分析改变了内存使用情况(为了更好)

时间:2011-07-29 19:54:43

标签: haskell memory-profiling

这实际上是this问题的后续问题。 我设法让分析工作,问题似乎真的是懒惰的评价。

我使用的数据结构是Map Int (Map Int Text),其中Text来自Data.Text。问题是,构建此映射的函数会产生巨大的影响。处理大约3 MB的输入文本时,程序需要超过250 MB的内存。

现在达到这个问题的真正目的:

要获取此数据结构中的字符数,请使用以下函数:

type TextResource = M.Map Int (M.Map Int T.Text)

totalSize :: TextResouce -> Int
totalSize = M.fold ((+) . (M.fold ((+). T.length) 0)) 0

不漂亮,但它完成了工作。我在创建TextResource后立即在main函数中使用此函数。有趣的是,当我使用RTS选项-hr-hc对程序进行概要分析时,内存使用量会在一段时间后降至70或50 MB,这将是完全正常的。

不幸的是,只有在使用性能分析选项和totalSize函数时才有效 - 如果没有它们,它会回到250 MB。

我将程序(< 70行)与测试文件和cabal文件一起上传,以便您自己试用:Link

test.xml是生成的XML文件,应放入executables目录中。 要构建,cabal configure --enable-executable-profiling和之后cabal build应该足够了(如果您安装了所需库的分析版本)。

使用+RTS -hc一次运行程序时可以看到更改,一次没有。

如果有人可以运行这个程序我真的很棒,因为我真的被困在这里。我已经尝试在几个地方放入deepseq,但没有任何作用(好吧,除了使用分析选项)。

修改

  

然而,分析确实表明只使用了大约20MB的堆,因此在我的评论中,我责备GHC没有像你想要的那样释放尽可能多的GC托儿所内存。

谢谢,这使我指出了正确的方向。事实证明,你可以告诉GHC执行垃圾收集(performGC),这在深度调整地图后非常有效。虽然我猜不推荐使用performGC,但这似乎是适合这项工作的正确工具。

EDIT2: 这是我改变main函数的方法(+ deepseqing返回buildTextFile):

main = do tf <- buildTextFile "test.xml"
          performGC
          putStrLn . show . text 1 1000 $ tf
          getLine
          putStrLn . show . text 100 1000 $ tf
          return ()

1 个答案:

答案 0 :(得分:4)

  

问题是,构建此映射的函数会产生巨大的影响。

没有。基于堆分析,我不相信空间使用是thunk。此外,我已使用严格的HashMaps替换Data.Map并强制使用相同结果的地图(以避免产生大的thunk)。

  

当我使用RTS选项-hr或-hc配置程序时,内存使用量会在一段时间后降至70或50 MB

我无法重现这一点。使用-hr-hy-hc进程保留140MB堆。然而,分析确实表明只使用了大约20MB的堆,因此在我的评论中,我责怪GHC没有像你想要的那样释放尽可能多的GC托儿所内存。

The -hy profile

对于计算期间的高内存使用,上述-hy配置文件显示大多数内存是由String类型和HaXML库Posn类型引起的。我将重申我的建议,即寻找一个基于ByteStringText的资源更加资源的XML库(xml-enumerator?)。