Я не думаю, что эта проблема обязательно связана с вводом / выводом.Скорее, это демонстрирует, что экземпляр Read
для Int
довольно неэффективен.
Сначала рассмотрим следующую программу, которая просто обрабатывает отложенный список.На моем компьютере требуется 4,1 с (скомпилировано с -O2
):
main = print $ sum' $ map read $ words
$ unwords $ map show $ replicate 500000 38000000
Замена функции read
на length
уменьшает время до 0,48 с:
main = print $ sum' $ map length $ words
$ unwords $ map show $ replicate 500000 38000000
Кроме того, замена функции read
на рукописную версию приводит к времени 0,52 с:
main = print $ sum' $ map myread $ words
$ unwords $ map show $ replicate 500000 38000000
myread :: String -> Int
myread = loop 0
where
loop n [] = n
loop n (d:ds) = let d' = fromEnum d - fromEnum '0' :: Int
n' = 10 * n + d'
in loop n' ds
Я думаю, почему read
настолько неэффективен, что его реализация использует Text.ParserCombinators.ReadP
модуль, который может оказаться не самым быстрым выбором для простого случая чтения одного целого числа.