(私が持っている)カスタムエンコード関数を使用して、大きな値リストをシリアライズする必要があります。私はこれを行って、それが動作しますが、私はまた、どれだけ多くの値がシリアル化され、ディスクに書き込まれている間、比較的一定量のメモリを使用しているのかをカウントしたいと思います(つまり、それは非常に大)を取得するように、周りのリスト。値リストのシリアライズとカウント
カウントを保持する必要がなく、バイナリ、シリアル、ブレーズ作成者がすべて機能します(B.writeFile "foo" . runPut . mapM_ encodeValue
相当)。しかし、私がこれらのライブラリを使って何をしようとしても、結果のByteStringは、チャンクが利用可能になるとすぐにディスクに書き込まれるのではなく、完了するまでメモリ内に保持されているようです(toByteStringIO
をblaze -ビルダー)。
これは私がやろうとしてきたものを証明する最小限の例です。
import Data.Binary
import Data.Binary.Put
import Control.Monad(foldM)
import qualified Data.ByteString.Lazy as B
main :: IO()
main = do let ns = [1..10000000] :: [Int]
(count,b) = runPutM $ foldM (\ c n -> c `seq` (put n >> return (c+1))) (0 :: Int) ns
B.writeFile "testOut" b
print count
コンパイルと+RTS -hy
で実行すると、結果は値をバイト文字列によって支配され、ほぼ三角形のグラフです。
私が今までに見つけた唯一の解決策(私が大ファンではない)は、Putまたは直接ビルドの値よりもむしろB.appendFile
を使用してIO内のループ(直接またはfoldM
)を行うことです私にはそれほどエレガントではないようです。より良い方法がありますか?
なぜ他の値ではなく8192ですか?そして、iterateeで見つけられなかったので、どこで 'run'関数の定義と型を見つけることができますか? – ivanm
私はあなたのソリューションが私自身の解決策を持っていた問題を実証していると思いますが、ByteStringを構築して、同時にいくつの値があるのかを数えることはできないようです。あなたはディスクに書き込む間にそれをしなければならないようです。 – ivanm
ああ、あなたがしていることは、私の元のバージョンとは異なる面があります。あなたのコードを理解すれば、番号ではなくディスクに保存された**バイト数**を返して印刷しています。 **値**のしたがって、それは間違っています:( – ivanm