首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >parsec内存不足

parsec内存不足
EN

Stack Overflow用户
提问于 2015-06-14 11:25:59
回答 1查看 240关注 0票数 0

我为一个大的csv文件写了一个解析器,它在一个较小的子集上工作,但在大约150万行(实际文件)的内存中耗尽。在最初将所有元素解析成一个列表(使用manyTill)之后,我转而使用解析器状态将它们存储在单个二进制搜索树中-这适用于大文件。

从那以后,我将“元素类型”分成了三个不同的类型,并希望将它们存储在自己的树中,从而产生三个不同类型的树。然而,这个版本只适用于较小的测试文件,而对于较大的测试文件则会耗尽内存。

代码语言:javascript
复制
import qualified Data.Tree.AVL as AVL
import qualified Text.ParserCombinators.Parsec as Parsec
----
data ENW = ENW (AVL.AVL Extent) (AVL.AVL Node) (AVL.AVL Way)
---- used to be Element = Extent | Node | Way  in a (Tree Element) - this worked
csvParser :: Parsec String ENW ENW
csvParser = do (Parsec.manyTill (parseL) Parsec.eof) >> Parsec.getState
    where parseL = parseLine >> ((Parsec.newline >> return ()) <|> Parsec.eof)

parseLine :: Parsec String ENW ()
parseLine = parseNode <|> parseWay <|> parseExtents

parseNode :: Parsec String ENW ()
parseNode = Parsec.string "node" *> (flip addNode <$> (Node <$> identifier <*> float <*> float)) >>= Parsec.updateState
    where identifier = Parsec.tab *> (read <$> Parsec.many1 Parsec.digit)
          float      = Parsec.tab *> (read <$> parseFloat)

addNode :: ENW -> Node -> ENW
addNode (ENW e n w) node  = (ENW e (AVL.push (sndCC node) node n) w)

parseWay和parseExtent遵循相同的模式,整个过程从

代码语言:javascript
复制
Parsec.runParser csvParser (ENW AVL.empty AVL.empty AVL.empty) "" input

我不明白为什么使用三个较小的树而不是一个大的树会导致内存问题。

EN

回答 1

Stack Overflow用户

发布于 2015-06-14 12:10:52

你有充分的理由不使用Cassava吗?它可用于流式传输CSV数据,并且可能比即席CSV解析器更健壮。我自己使用它的经验表明,它具有出色的性能,并且可以很容易地扩展到解析您自己的类型。

编辑:看起来你使用的是制表符分隔的值数据,而不是逗号分隔的数据,但是Cassava允许你指定要分割列的分隔符,它还显示你在每行上的数据可能不同,所以你可能需要使用Cassava的“原始”格式,它为每一行返回一个矢量ByteString,然后你可以根据第一个元素进行解析。

我从来没有见过有人使用AVL tree包,你有没有一个好的理由不使用更多的标准结构?这个包很旧(上一次更新是在2008年),最近的包可能会表现得更好。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30825686

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档