私はData.Binary.PutMモナドをモナドトランスに変更しようとしています。なぜData.Binary.Putモナドを変圧器に変更するとメモリリークが発生するのですか?
:
だから私は その後newtype PutM a = Put { unPut :: Identity (PairS a) }
に
newtype PutM a = Put { unPut :: PairS a }
からの定義をCHANGINによって開始されたが、もちろん私はリターンと>> =関数の実装を変更しました
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 (>>) #-}
To:
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モナドが単なるWriterモナドであるかのように。残念ながら、これは(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ではありません。 –
こんにちは@stephen、私は元のData.Binary.Putモナド(それにアイデンティティのないもの)を使用する場合、それはうまくストリーミングしています(顕著なメモリの増加はありません)。メモリが純粋にツリー構造によって消費された場合、メモリの増加はどちらの場合でも明らかになります。 –
さらにコードを送ってもらえますか? – fuz