Pet*_*iak 12 memory binary haskell memory-leaks memory-management
我正在尝试将Data.Binary.Put monad包装到另一个monad中,以便稍后我可以问一些问题,例如"它要写多少字节"或"文件中的当前位置是什么".但即使非常微不足道的包装如下:
data Writer1M a = Writer1M { write :: P.PutM a }
or
data Writer2M a = Writer2M { write :: (a, P.Put) }
Run Code Online (Sandbox Code Playgroud)
创建一个巨大的空间泄漏,程序通常崩溃(占用4GB的RAM后).这是我到目前为止所尝试的:
-- This works well and consumes almost no memory.
type Writer = P.Put
writer :: P.Put -> Writer
writer put = put
writeToFile :: String -> Writer -> IO ()
writeToFile path writer = BL.writeFile path (P.runPut writer)
Run Code Online (Sandbox Code Playgroud)
-- This one will cause memory leak.
data Writer1M a = Writer1M { write :: P.PutM a }
instance Monad Writer1M where
return a = Writer1M $ return a
ma >>= f = Writer1M $ (write ma) >>= \a -> write $ f a
type WriterM = Writer1M
type Writer = WriterM ()
writer :: P.Put -> Writer
writer put = Writer1M $ put
writeToFile :: String -> Writer -> IO ()
writeToFile path writer = BL.writeFile path (P.runPut $ write writer)
Run Code Online (Sandbox Code Playgroud)
-- This one will crash as well with exactly the
-- same memory foot print as Writer1M
data Writer2M a = Writer2M { write :: (a, P.Put) }
instance Monad Writer2M where
return a = Writer2M $ (a, return ())
ma >>= f = Writer2M $ (b, p >> p')
where (a,p) = write ma
(b,p') = write $ f a
type WriterM = Writer2M
type Writer = WriterM ()
writer :: P.Put -> Writer
writer put = Writer2M $ ((), put)
writeToFile :: String -> Writer -> IO ()
writeToFile path writer = BL.writeFile path (P.runPut $ snd $ write writer)
Run Code Online (Sandbox Code Playgroud)
我是Haskell的新手,这对我没有任何意义,但封装monad看起来非常微不足道,所以我猜我有一些明显缺失的东西.
谢谢你的期待.
更新:以下是演示此问题的示例代码:http://hpaste.org/43400/why_wrapping_the_databinaryp
UPDATE2:还有第二部分,这个问题在这里.
经过一番研究,我发现问题似乎是使用二进制的 (>>=) 来实现 (>>)。对 Writer1M monad 实现添加以下内容可以解决该问题:
m >> k = Writer1M $ write m >> write k
Run Code Online (Sandbox Code Playgroud)
然而这个版本仍然存在内存泄漏:
m >> k = Writer1M $ write m >>= const (write k)
Run Code Online (Sandbox Code Playgroud)
查看二进制文件的源代码, (>>) 似乎明确丢弃了第一个 monad 的结果。但不确定这到底是如何防止泄漏的。我最好的理论是,否则 GHC 会保留 PairS 对象,并且“a”引用会泄漏,因为它永远不会被查看。
归档时间: |
|
查看次数: |
679 次 |
最近记录: |