haskell - 惰性 IO - 字符串未被垃圾收集?

标签 haskell

我目前正在尝试将 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 con)。我得出这个结论是因为对于非常大的 XML 文件,内存消耗会迅速上升,虽然生成的 TextFile 只是单例映射的单例映射(使用特殊的测试文件,一般它是不同的,当然).所以最后,我有一个 Map Int StringMap,里面只有一个字符串,但是内存消耗高达 19 MB。

使用严格的应用程序 ($!) 或使用 Data.Text 而不是 TextFile 中的 String 不会不要改变任何东西。

所以我的问题是:有什么方法可以告诉编译器字符串 content(或 doccon)不是不再需要它并且它可以被垃圾收集?

更一般地说:如何在不进行所有猜测的情况下找出问题的真正来源?

编辑:正如 FUZxxl 所建议的,我尝试使用 deepseq 并更改了 buildTextFile 的第二行,如下所示:

let doc = content `deepseq` xmlParse filename content

不幸的是,这并没有真正改变任何东西(或者我用错了吗?)...

最佳答案

不要猜测什么在消耗内存,要确定

第一步是确定哪些类型消耗的内存最多。您可以在 SO 上看到大量堆分析示例或阅读 GHC manual .

强制计算

如果问题是惰性求值(您正在构建一个可以计算 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

或者只使用 bang 模式 (!res = buildTF con),无论哪种方式都应该强制 thunk 并允许 GC 收集 String

关于haskell - 惰性 IO - 字符串未被垃圾收集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6764075/

相关文章:

haskell - 什么是克罗克福德定律?

haskell - 是否可以在 Haskell 中否定类型参数约束?

haskell - 为什么这个递归函数没有被优化? ( haskell )

haskell - stack.yaml 文件是否应该检查到版本控制中?

Haskell - 具有类约束的 GADT 模式匹配

haskell - 使用 ResourceT 时需要提升的说明

if-statement - Haskell 函数返回列表中出现次数超过给定数量的元素列表

haskell - 如何在 Cabal 中将命令行选项传递给 Alex

haskell - 在 Ubuntu 12.04 上勇敢面对阴谋 hell

haskell - 将值映射转换为元组列表