懒惰的IO - 字符串不是垃圾收集?

时间:2011-07-20 15:06:06

标签: 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或{ {1}})。我得出这个结论是因为内存消耗随着非常大的XML文件而迅速上升,尽管结果con只是单例映射的单例映射(使用特殊的测试文件,当然通常它是不同的)。所以最后,我有一个TextFile Map,其中只有一个字符串,但内存消耗最多为19 MB。

Map Int String中使用严格的申请($!)或使用Data.Text代替String不会改变任何内容。

所以我的问题是:是否有某种方法可以告诉编译器不再需要字符串TextFile(或contentdoc)并且可以进行垃圾回收?

更一般地说:如果没有猜测,我怎样才能找出问题的真正来源?

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

buildTextFile

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

1 个答案:

答案 0 :(得分:2)

不要猜猜什么是消耗内存,一目了然

第一步是确定消耗最多内存的类型。你可以在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

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

相关问题