Чтение большого файла в haskell?

Я пытался прочитать большой файл в haskell.

Мне нужно сжать его с помощью пользовательского алгоритма для университетского проекта. Все работает хорошо, пока я не начинаю сжимать большие файлы.

Я извлек из своей программы то, что шло не так, и изложил это здесь в форме "Hello big file":

import System
import qualified Data.ByteString.Lazy as BL
import Data.Word

fold_tailrec :: (a -> b -> a) -> a -> [b] -> a
fold_tailrec _ acc [] =
    acc
fold_tailrec foldFun acc (x : xs) =
    fold_tailrec foldFun (foldFun acc x) xs

fold_tailrec' :: (a -> b -> a) -> a -> [b] -> a
fold_tailrec' _ acc [] =
    acc
fold_tailrec' foldFun acc (x : xs) =
    let forceEval = fold_tailrec' foldFun (foldFun acc x) xs in
    seq forceEval forceEval

main :: IO ()
main =
    do
        args <- System.getArgs
        let filename = head args
        byteString <- BL.readFile filename
        let wordsList = BL.unpack byteString
        -- wordsList is supposed to be lazy (bufferized)
        let bytesCount = fold_tailrec (\acc word -> acc + 1) 0 wordsList
        print ("Total bytes in " ++ filename ++ ": " 
               ++ (show bytesCount))

Я назвал этот файл Test.hs, затем сделал следующее:

$ ls -l toto
-rwxrwxrwx 1 root root 5455108 2011-03-23 19:08 toto
$ ghc --make -O Test.hs
[1 of 1] Compiling Main             ( Test.hs, Test.o )
Linking Test ...
$ ./Test toto
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
$ ./Test toto +RTS -K50M -RTS
Stack space overflow: current size 50000000 bytes.
Use `+RTS -Ksize -RTS' to increase it.
$ ./Test toto +RTS -K500M -RTS
"Total bytes in toto: 5455108"
$ time ./Test toto +RTS -K500M -RTS
"Total bytes in toto: 5455108"

real    0m33.453s
user    0m8.917s
sys 0m10.433s

Кто-нибудь может объяснить, почему мне нужно 500 мегабайт RAM и 30 секунд CPU, чтобы просмотреть жалкий файл размером 5 мегабайт? Пожалуйста, что я делаю не так? Почему [word8] не буферизируется, как указано в документации ByteString. И как это исправить?

Я пытался определить свой собственный хвост рекурсивной складки вместо foldl, foldr или foldl'. Я пробовал также размораживать бантики с помощью seq. Пока не получил никакого результата.

Спасибо за любую помощь, потому что я застрял.

18
задан Don Stewart 24 April 2011 в 16:30
поделиться