2011-11-09 89 views
6

所以,我已经使用了几个Haskell XML库,包括hexpat和xml-enumerator。在阅读Real World Haskell中的IO章节后(http://book.realworldhaskell.org/read/io.html),我的印象是,如果我运行下面的代码,它会在我经历它时收集垃圾。Haskell解析低内存的大xml文件

但是,当我在大文件上运行它时,内存使用量在运行时会不断攀升。

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 

我的最终目标是用一个简单的萨克斯类接口来解析一个巨大的xml文件。我不想让整个结构知道我发现了一个“事件”。

+1

编译它而不是在解释模式下运行时,你是否也得到这种行为? – hammar

+0

编译时不要忘记使用优化(-O2)。 –

+0

你是否需要编译并优化才能将其收集到垃圾回收中?如果是这样,我一定会在将来尝试 –

回答

8

我是hexpat的维护者。这是一个错误,我现在用hexpat-0.19.8修复了这个错误。感谢您提请我注意。

这个错误是ghc-7.2.1的新问题,它涉及到一个交互,我没有想到在where子句绑定到三元组和unsafePerformIO之间,我需要与C进行交互代码在Haskell中显得纯粹。

+0

现在,我称之为维护者!好的工作blackh。 –

3

这似乎是一个问题与十六进制。运行编译后的优化,仅用于简单的任务,如length,会导致线性内存使用。

看着hexpat,我认为有过多的缓存正在进行(请参阅parseG函数)。我建议联系hexpat维护者(s)并询问这是否是预期的行为。它应该在haddocks中被提及,但是资源消耗似乎在图书馆文档中经常被忽略。

+0

从[快速堆配置文件](http://i.stack.imgur.com/8mYdh.png),它看起来大部分来自泄漏' (:)'构造函数。 – hammar

+0

很高兴知道我的假设没有错。我想我会继续讨论其他软件包。谢谢! –