ram*_*ion 15 memory haskell parsec
我有一个279MB的文件,包含大约1000万个键/值对,大约有500,000个唯一键.它按键分组(每个键只需要写一次),因此给定键的所有值都在一起.
我想要做的是转换关联,创建一个文件,其中对按值分组,给定值的所有键都存储在一起.
目前,我正在使用Parsec作为元组列表读取对(K,[V])(使用惰性IO,因此我可以在Parsec处理输入文件时将其作为流处理),其中:
newtype K = K Text deriving (Show, Eq, Ord, Hashable)
newtype V = V Text deriving (Show, Eq, Ord, Hashable)
tupleParser :: Parser (K,[V])
tupleParser = ...
data ErrList e a = Cons a (ErrList e a) | End | Err e
parseAllFromFile :: Parser a -> FilePath-> IO (ErrList ParseError a)
parseAllFromFile parser inputFile = do
contents <- readFile inputFile
let Right initialState = parse getParserState inputFile contents
return $ loop initialState
where loop state = case unconsume $ runParsecT parser' state of
Error err -> Err err
Ok Nothing _ _ -> End
Ok (Just a) state' _ -> a `Cons` loop state'
unconsume v = runIdentity $ case runIdentity v of
Consumed ma -> ma
Empty ma -> ma
parser' = (Just <$> parser) <|> (const Nothing <$> eof)
Run Code Online (Sandbox Code Playgroud)
我试图将元组插入Data.HashMap.Map V [K]到转换关联中:
transpose :: ErrList ParseError (K,[V]) -> Either ParseError [(V,[K])]
transpose = transpose' M.empty
where transpose' _ (Err e) = Left e
transpose' m End = Right $ assocs m
transpose' m (Cons (k,vs) xs) = transpose' (L.foldl' (include k) m vs) xs
include k m v = M.insertWith (const (k:)) v [k] m
Run Code Online (Sandbox Code Playgroud)
但是当我尝试它时,我得到了错误:
memory allocation failed (requested 2097152 bytes)
Run Code Online (Sandbox Code Playgroud)
我能想到一些我做错的事情:
我现在倾向于(1),但我不确定.
Kni*_*ins -1
为了允许大于可用内存的文件,最好一次以一口大小的块来处理它们。
这是将文件 A 复制到新文件 B 的可靠算法:
将文件 A 的副本复制到临时文件夹中并在使用它时将其锁定,这样网络上的其他人就不会被阻止更改原始文件,但您拥有该文件的快照,这也是值得的此时程序开始。
我打算将来重新审视这个答案并添加代码。