在我搜索可以处理大型(300-1000mb)xml文件的 haskell库时,我遇到了 hexpat.Haskell Wiki中有 an example声称 -- Process document before handling error, so we get lazy processing. 出于测试目的,我已将输出重定向到
-- Process document before handling error, so we get lazy processing.
出于测试目的,我已将输出重定向到/ dev / null并在其上抛出300mb文件.内存消耗不断上升,直到我不得不杀死进程.
现在我从流程函数中删除了错误处理:
process :: String -> IO () process filename = do inputText <- L.readFile filename let (xml, mErr) = parse defaultParseOptions inputText :: (UNode String, Maybe XMLParseError) hFile <- openFile "/dev/null" WriteMode L.hPutStr hFile $format xml hClose hFile return ()
结果,该函数现在使用常量内存.为什么错误处理会导致大量内存消耗?
据我所知,xml和mErr在调用解析后是两个单独的未评估的thunk.格式化xml是否评估xml并构建’mErr’的评估树?如果是,是否有办法在使用常量内存时处理错误?
http://www.haskell.org/haskellwiki/Hexpat/
我不能说有关hexpat的权限,但一般来说,错误处理会强制你将整个文件读入内存.如果只想在输入中的任何位置没有错误时打印出结果,则需要在生成输出之前读取整个输入.正如我所说,我真的不知道hexpat,但是使用xml-conduit,你可以做类似的事情:
try $runResourceT $parseFile def inputFile $$renderBytes def =$sinkFile outputFile
它将使用常量内存,如果处理中有任何错误,它将抛出异常(try会捕获).缺点是输出文件可能已损坏.我的猜测是你最好输出到一个临时文件,在整个过程完成后,将临时文件移动到输出文件.在任何异常上,只需删除临时文件即可.