这实际上是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 ()
答案 0 :(得分:4)
问题是,构建此映射的函数会产生巨大的影响。
没有。基于堆分析,我不相信空间使用是thunk。此外,我已使用严格的HashMaps替换Data.Map
并强制使用相同结果的地图(以避免产生大的thunk)。
当我使用RTS选项-hr或-hc配置程序时,内存使用量会在一段时间后降至70或50 MB
我无法重现这一点。使用-hr
,-hy
或-hc
进程保留140MB堆。然而,分析确实表明只使用了大约20MB的堆,因此在我的评论中,我责怪GHC没有像你想要的那样释放尽可能多的GC托儿所内存。
对于计算期间的高内存使用,上述-hy
配置文件显示大多数内存是由String
类型和HaXML库Posn
类型引起的。我将重申我的建议,即寻找一个基于ByteString
或Text
的资源更加资源的XML库(xml-enumerator?)。