【问题标题】:Haskell parse big xml file with low memoryHaskell解析内存不足的大xml文件
【发布时间】:2011-12-25 09:53:37
【问题描述】:

所以,我使用了几个 Haskell XML 库,包括 hexpat 和 xml-enumerator。在阅读了 Real World 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 文件。我不想知道整个结构才能得到通知我发现了一个“事件”。

【问题讨论】:

  • 在编译它而不是在解释模式下运行它时,你是否也会得到这种行为?
  • 编译时不要忘记使用优化(-O2)。
  • 您是否必须编译和优化才能使其进行垃圾收集?如果是这样,我一定会在未来尝试一下

标签: xml memory haskell stream expat-parser


【解决方案1】:

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

该错误是 ghc-7.2.1 上的新错误,它与绑定到三元组的 where 子句与 unsafePerformIO 之间的交互有关,我需要与 C 代码进行交互在 Haskell 中看起来很纯粹。

【讨论】:

    【解决方案2】:

    这似乎是 hexpat 的问题。运行已编译、优化并仅针对 length 之类的简单任务,会导致线性内存使用。

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

    【讨论】:

    • 来自a quick heap profile,看起来大部分来自泄漏的(:)构造函数。
    • 很高兴知道我的假设没有错。我想我会继续搞乱其他包。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2015-06-18
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多