这实际上是这个问题的后续问题。我设法让分析工作,问题似乎真的是懒惰的评估。
我使用的数据结构是 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 ()