Haskell解析内存不足的大xml文件

时间:2011-11-09 15:19:17

标签: xml memory haskell stream expat-parser

所以,我已经使用了几个Haskell XML库,包括hexpat和xml-enumerator。在阅读了真实世界Haskell(http://book.realworldhaskell.org/read/io.html)中的IO章节之后,我的印象是,如果我运行以下代码,那么在我浏览它时它将被垃圾收集。

然而,当我在一个大文件上运行它时,内存使用量在运行时不断攀升。

runghc parse.hs bigfile.xml

我做错了什么?我的假设错了吗?地图/过滤器是否强制它评估所有内容?

import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Lazy.UTF8 as U
import Prelude hiding (readFile)
import Text.XML.Expat.SAX 
import System.Environment (getArgs)

main :: IO ()
main = do
    args <- getArgs
    contents <- BSL.readFile (head args)
    -- putStrLn $ U.toString contents
    let events = parse defaultParseOptions contents 
    mapM_ print $ map getTMSId $ filter isEvent events

isEvent :: SAXEvent String String -> Bool 
isEvent (StartElement "event" as) = True
isEvent _ = False

getTMSId :: SAXEvent String String -> Maybe String
getTMSId (StartElement _ as) = lookup "TMSId" as

我的最终目标是使用简单的类似sax的界面解析一个巨大的xml文件。我不想知道整个结构,以通知我发现了一个“事件”。

2 个答案:

答案 0 :(得分:8)

我是hexpat的维护者。这是一个错误,我现在已经修复了hexpat-0.19.8。感谢您引起我的注意。

这个bug在ghc-7.2.1上是新的,它与我在绑定到三元组的where子句和unsafePerformIO之间没有预料到的交互有关,我需要与C代码进行交互。在Haskell看来是纯粹的。

答案 1 :(得分:3)

这似乎是hexpat的一个问题。运行已编译,优化,仅用于length这样的简单任务,会导致线性内存使用。

看看hexpat,我认为存在过多的缓存(参见parseG函数)。我建议联系hexpat维护者并询问这是否是预期的行为。它应该在黑线鳕中以任何一种方式提到,但在图书馆文档中似乎经常忽略资源消耗。