我试图修改Data.Binary.PutM monad成monad变换器。于是我开始了变化它的定义从为什么将Data.Binary.Put monad更改为变换器会产生内存泄漏?
newtype PutM a = Put { unPut :: PairS a }
到
newtype PutM a = Put { unPut :: Identity (PairS a) }
那么当然我改变了回报和>> =函数的实现:
来源:
return a = Put $ PairS a mempty
{-# INLINE return #-}
m >>= k = Put $
let PairS a w = unPut m
PairS b w1 = unPut (k a)
in PairS b (w `mappend` w1)
{-# INLINE (>>=) #-}
m >> k = Put $
let PairS _ w = unPut m
PairS b w1 = unPut k
in PairS b (w `mappend` w1)
{-# INLINE (>>) #-}
收件人:
return a = Put $! return $! PairS a mempty
{-# INLINE return #-}
m >>= k = Put $!
do PairS a w <- unPut m
PairS b w1 <- unPut (k a)
return $! PairS b $! (w `mappend` w1)
{-# INLINE (>>=) #-}
m >> k = Put $!
do PairS _ w <- unPut m
PairS b w1 <- unPut k
return $! PairS b $! (w `mappend` w1)
{-# INLINE (>>) #-}
好像PutM monad只是一个Writer monad。不幸的是(again)造成了空间泄漏。我很清楚(或是否?)ghc推迟评估某处,但我尝试将$!
而不是$
无处不在,正如某些教程所建议的,但这并没有帮助。另外,我不确定内存分析器是如何帮助的,如果它告诉我的是这样的:
。
以及物品是否完整,这是存储配置文件使用原始Data.Binary.Put单子时,我得到:
如果有兴趣,here是我使用来测试它的代码和我使用的编译,运行和创建存储轮廓线是:
ghc -auto-all -fforce-recomp -O2 --make test5.hs && ./test5 +RTS -hT && hp2ps -c test5.hp && okular test5.ps
我希望我不是被我的内存泄漏问题传奇讨厌任何人。我发现互联网上没有很多关于这个话题的良好资源,这让我们无言以对。
感谢您的期待。
彼得嗨 - 我不相信你有内Data.Binary即“太空泄漏”一些错误的数据处理停止垃圾收集。我想为什么你要构建一个巨大的内存配置文件是因为你的数据结构(一棵树)没有流 - 在完成序列化之前它必须在内存中(加上一个类似的大输出ByteString)。我的直觉是问题是树 - 而不是Data.Binary。 – 2011-03-09 12:58:00
嗨@stephen,我忘了提及,如果我使用原始的Data.Binary.Put monad(没有Identity的那个),那么它流很好(没有通知的内存增加)。我的理解是,如果记忆纯粹是由树结构消耗的,记忆力的增加会在两种情况下表现出来。 – 2011-03-09 13:23:34
你能给我们发一些更多的代码吗? – fuz 2011-03-09 13:27:30