我正在使用import Text.Parsec.Text
和import Text.Parsec.Char
解析某些包含整数的数据。我正在使用以下代码来解析整数。
p_int :: Parser Int
p_int = read <$> ((++) <$> option "" (string "-") <*> many1 digit)
我剖析了我的程序,结果是上面的代码片段占用了90%以上的执行时间。如何优化以上代码?
我遇到了Text.ParserCombinators.Parsec.Number
模块,其中包含一个int
函数来解析整数。但是,其类型为int :: Integral i => CharParser st i
,与我正在使用的基于Text
的解析器不兼容,如下面的错误所示。
• Couldn't match type ‘[Char]’ with ‘Text’
Expected type: Parser Int
Actual type: Text.ParserCombinators.Parsec.Char.CharParser () Int
UPDATE我用Text.Parsec.Text
替换了Text.Parsec.String
,并用int
的Text.ParserCombinators.Parsec.Number
替换了我的int解析函数。这将执行时间缩短了约40%。但是性能仍然不如Python。分析表明,在int解析中消耗了大约80%的时间。这是否意味着Parsec速度很慢?
COST CENTRE MODULE SRC %time %alloc
sign Text.ParserCombinators.Parsec.Number Text/ParserCombinators/Parsec/Number.hs:277:1-73 34.4 39.8
number Text.ParserCombinators.Parsec.Number Text/ParserCombinators/Parsec/Number.hs:(321,1)-(323,18) 26.7 27.5
numberValue Text.ParserCombinators.Parsec.Number Text/ParserCombinators/Parsec/Number.hs:(327,1)-(328,74) 10.2 6.7
zeroNumber Text.ParserCombinators.Parsec.Number Text/ParserCombinators/Parsec/Number.hs:(300,1)-(301,56) 6.0 10.0
...
....
int Text.ParserCombinators.Parsec.Number Text/ParserCombinators/Parsec/Number.hs:273:1-17 499 0 1.4 1.6 79.5 86.5
我用Attoparsec替换了Parsec,并且没有进行任何优化,现在速度提高了80%。另外,“总分配”从3GB以上降至507MB。
两个库之间的API非常相似,因此完全不难迁移。如果可能,我将尝试进一步优化它,并查看它能获得多快。