我目前正在尝试将 XML 文件的内容读入Map Int (Map Int String)
而且效果很好(使用 HaXml)。但是,我对程序的内存消耗不满意,问题似乎是垃圾收集。
这是我用来读取 XML 文件的代码:
type TextFile = Map Int (Map Int String)
buildTextFile :: String -> IO TextFile
buildTextFile filename = do content <- readFile filename
let doc = xmlParse filename content
con = docContent (posInNewCxt filename Nothing) doc
return $ buildTF con
我的猜测是content
即使返回后也保留在内存中,尽管它不需要(当然也可以是doc
or con
)。我得出这个结论是因为 XML 文件非常大时,内存消耗会迅速增加,尽管由此产生的结果TextFile
只是单例映射的单例映射(使用特殊的测试文件,当然通常是不同的)。所以最后,我有一个Map
of a Map Int String
,只有一个字符串,但内存消耗高达19MB。
使用严格的应用程序($!
)或使用Data.Text
代替String
in TextFile
并没有改变任何东西。
所以我的问题是:有没有办法告诉编译器该字符串content
(or doc
or con
)不再需要并且可以被垃圾收集?
更一般地说:我怎样才能在不猜测的情况下找出问题的真正根源?
Edit:正如 FUZxxl 建议的那样,我尝试使用 deepseq 并更改了第二行buildTextFile
像这样:
let doc = content `deepseq` xmlParse filename content
不幸的是,这并没有真正改变任何东西(或者我用错了?)......
不要猜测什么消耗了内存,而是确定地找出来
第一步是确定哪些类型消耗的内存最多。您可以在 SO 上看到很多堆分析的示例,或者阅读GHC手册 http://www.haskell.org/ghc/docs/7.0.2/html/users_guide/prof-heap.html.
强制计算
If问题是惰性求值(您正在构建一个可以计算 XML 文档类型并将字符串留在堆中的堆上 thunk),然后使用 rnf 和 seq:
buildTextFile :: String -> IO TextFile
buildTextFile filename = do content <- readFile filename
let doc = xmlParse filename content
con = docContent (posInNewCxt filename Nothing) doc
res = buildTF con
return $ rnf res `seq` res
或者只使用刘海图案(!res = buildTF con
),无论哪种方式都应该强制 thunk 并允许 GC 收集String
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)