8

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

我使用的数据结构是 a 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文件一起上传了,你可以自己试试:链接

test.xml 是一个生成的 XML 文件,应该放在可执行文件目录中。构建,cabal configure --enable-executable-profiling然后cabal build就足够了(如果您安装了所需库的分析版本)。

+RTS -hc您可以在运行程序一次和一次不运行时看到变化。

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

编辑:

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

谢谢,这为我指明了正确的方向。事实证明,您可以告诉 GHC 执行垃圾收集 ( performGC ),它在对地图进行深度处理后效果非常好。尽管我猜不推荐使用 performGC,但它似乎是适合这里工作的工具。

Edit2: 这就是我更改主函数的方式(+ deepseqing buildTextFile 的返回):

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

1 回答 1

4

问题是,构建此地图的函数会产生巨大的冲击。

不。基于堆分析,我不相信空间使用是 thunk。此外,我已替换Data.Map为严格的 HashMaps 并强制映射(以避免创建大的 thunk)具有相同的结果。

当我使用 RTS 选项 -hr 或 -hc 分析程序时,一段时间后内存使用量下降到 70 或 50 MB

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

-hy 配置文件

至于计算期间的高内存使用,上面的-hy配置文件显示大部分内存是由于String类型和 HaXML 库Posn类型。我将重申我的建议,即寻找一个ByteStringText基于 XML 库的资源意识更强的库(xml-enumerator?)。

于 2011-07-29T22:41:22.037 回答