Haskell Parse c - Оптимизировать анализ - PullRequest
3 голосов
/ 15 января 2020

Я использую 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

ОБНОВЛЕНИЕ Я заменил Text.Parsec.Text с Text.Parsec.String и заменил мою функцию синтаксического анализа int на int с Text.ParserCombinators.Parsec.Number. Это улучшило время выполнения на ~ 40%. Но все же производительность хуже, чем Python. Профилирование показывает, что ~ 80% времени затрачивается на разбор int Означает ли это, что Parse c просто медленный?

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

1 Ответ

1 голос
/ 17 января 2020

Я заменил Parse c на Attoparse c, и без какой-либо оптимизации он теперь работает на 80% быстрее. Кроме того, «all allo c» уменьшено с более 3 ГБ до 507 МБ.

API очень похож на две библиотеки, поэтому его было совсем не сложно перенести. Я постараюсь еще больше оптимизировать его, если это возможно, и посмотрю, как быстро он может работать

...