在ghci中将一个惰性字节串写入文件时内存爆炸

时间:2014-07-27 08:59:46

标签: haskell memory-leaks lazy-loading lazy-evaluation ghci

以下程序在运行可执行文件(通过ghc -O0 Explode.hs编译)时会爆炸,但在ghci中运行时爆炸(通过{{ 1}}或ghci Explode.hs):

ghci -fobject-code Explode.hs

为什么它会在ghci而不是--Explode.hs --Does not explode with : ghc -O0 Explode.hs --Explodes with : ghci Explode.hs --Explodes with : ghci -fobject-code Explode.hs module Main (main) where import Data.Int import qualified Data.ByteString.Lazy as BL import qualified Data.ByteString.Lazy.Char8 as BLC createStr :: Int64 -> String -> BL.ByteString createStr num str = BL.take num $ BL.cycle $ BLC.pack str main = do BLC.writeFile "results.txt" $ createStr 100000000 "abc\n" 中爆炸,我怎样才能阻止它在ghci中爆炸?我在Memory blowing up for strict sum/strict foldl in ghci中采用的方法似乎不适用于此。感谢。

1 个答案:

答案 0 :(得分:2)

在检查writeFile的代码后,它似乎取决于hPut的{​​{1}}函数:

Data.ByteString.Lazy

-- | Outputs a 'ByteString' to the specified 'Handle'. -- hPut :: Handle -> ByteString -> IO () hPut h cs = foldrChunks (\c rest -> S.hPut h c >> rest) (return ()) cs 构造hPut动作,该动作将通过在块上应用右对齐来打印延迟字节串。 IO函数的来源是:

foldrChunks

查看代码,似乎在写入第一个字节之前,将强制执行lazy bytestring的“spine”(但不是每个chunk中的实际数据),因为-- | Consume the chunks of a lazy ByteString with a natural right fold. foldrChunks :: (S.ByteString -> a -> a) -> a -> ByteString -> a foldrChunks f z = go where go Empty = z go (Chunk c cs) = f c (go cs) 的行为对于(>>) monad。

在您的示例中,组成懒惰字节串的严格块非常小。这意味着当IO“强制执行100000000字符长延迟字节字符串的脊椎”时,将生成很多这些字符串。

如果这种分析是正确的,那么通过使它们变大来减少严格块的数量将减少内存使用量。 foldrChunks的这种变体可以创建更大的块,但这并不会让我在ghci中爆炸:

createStr

(我不确定为什么编译的例子不会爆炸。)