在计算大文件中的字符时耗尽内存

时间:2016-12-23 14:13:48

标签: haskell out-of-memory

我想计算一个大文件中每个字符的出现次数。虽然我知道计数应该在Haskell中严格实现(我试图使用foldl实现),但我仍然没有内存。作为比较:文件大小约为2GB,而计算机有100GB内存。该文件中没有太多不同的字符 - 可能是20.我做错了什么?

ins :: [(Char,Int)] -> Char -> [(Char,Int)]
ins [] c = [(c,1)]
ins ((c,i):cs) d
    | c == d = (c,i+1):cs
    | otherwise = (c,i) : ins cs d

main = do
    [file] <- getArgs
    txt <- readFile file
    print $ foldl' ins [] txt

1 个答案:

答案 0 :(得分:7)

您的ins函数正在创建大量thunks,导致大量memory leakfoldl'仅评估为weak head normal form,这还不够。您需要Control.DeepSeq来自import System.Environment (getArgs) import Data.Map.Strict (empty, alter) import qualified Data.ByteString.Lazy.Char8 as B main :: IO () main = getArgs >>= B.readFile . head >>= print . B.foldl' go empty where go = flip $ alter inc inc :: Maybe Int -> Maybe Int inc Nothing = Just 1 inc (Just i) = Just $ i + 1 才能获得普通表格

或者,使用deepseq进行计数,而不是关联列表。此外,如果您的IO大约为2GB,则最好使用Data.Map.Strict而不是普通字符串。

无论输入大小如何,Bellow代码都应在恒定的内存空间中执行:

{{1}}