2012-01-17 27 views
13

私はzlibを使用してテキストデータのストリームを圧縮しています。テキストデータはチャンクになり、チャンクごとにdeflate()が呼び出され、フラッシュはZ_NO_FLUSHに設定されます。一度すべてのチャンクが取得されると、deflate()が呼び出され、フラッシュはZ_FINISHに設定されます。zlib、deflate:割り当てるメモリ量は?

もちろん、deflate()は、各呼び出しで圧縮出力を生成しません。高い圧縮率を達成するために内部的にデータを蓄積します。そしてそれは大丈夫です! deflate()が圧縮出力を生成するたびに、その出力はデータベースフィールドに追加されます。

ただし、deflate()が圧縮データを生成すると、そのデータは提供された出力バッファに収まらない可能性があります。deflate_outしたがって、deflate()へのいくつかの呼び出しが必要です。

deflate()はその中のすべての圧縮データを格納できるように、十分なdeflate_outが常に大にする方法はあり、それは出力を生成することを決定し、すべての回:そして、それは私が避けたいものですか?

  • 非圧縮データの合計サイズが事前知りません。上記のように、圧縮されていないデータはチャンクになり、圧縮されたデータはデータベースのフィールドにもチャンクで付加されます。

  • インクルードファイルzconf.hに次のコメントがあります。それはおそらく私が探しているものですか?私。 deflate()が生成する圧縮データの最大サイズ(バイト単位)は(1 << (windowBits+2)) + (1 << (memLevel+9))ですか?ヒントのためのソースを見ながら

    /* The memory requirements for deflate are (in bytes): 
          (1 << (windowBits+2)) + (1 << (memLevel+9)) 
    that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) 
    plus a few kilobytes for small objects. For example, if you want to reduce 
    the default memory requirements from 256K to 128K, compile with 
        make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" 
    Of course this will generally degrade compression (there's no free lunch). 
    
        The memory requirements for inflate are (in bytes) 1 << windowBits 
    that is, 32K for windowBits=15 (default value) plus a few kilobytes 
    for small objects. 
    */ 
    
+0

http://stackoverflow.com/questions/4936255/zlib-how-to-dimension-avail-out – nos

+2

@nosを参照してください。これは、入力のサイズがわかっている場合にのみ役に立ちます。 –

+0

出力バッファのサイズではなく、圧縮のためのメモリ要件として 'zconf.h'のコメントを読んでいます。 出力バッファの上限は、合計メモリ要件(上記の例では128K + 128K +「数キロバイト」)+ヘッダー長(40バイト)です。 –

答えて

5

deflateBound()は、すべての圧縮を1つの手順で行う場合、または現在使用可能なすべての入力データをdeflateで強制的に圧縮し、すべての入力に対して圧縮データを出力する場合にのみ役立ちます。あなたはZ_BLOCK、Z_PARTIAL_FLUSHなどのフラッシュパラメータでこれを行うでしょう。

Z_NO_FLUSHを使いたい場合、出力の最大量を予測しようとするのははるかに難しくなり、非効率的になります。次の呼び出し時に放出します。圧縮データの最後のバーストが放出された時点でどれだけの入力が消費されたかは分かりませんので、バッファサイズが不必要に大きくなっているため、ほとんどそれを仮定する必要はありません。しかし、あなたは最大出力を見積もろうとしますが、無駄なmallocやreallocをたくさん実行するのは正当な理由がないため非効率です。

さらなる出力のためにdeflate()を呼び出すことを避けるべきポイントはありません。出力がなくなるまでdeflate()をループすれば、固定出力バッファを一度mallocすることができます。これは、deflate()とinflate()インタフェースがどのように使用されるように設計されたかです。 http://zlib.net/zlib_how.htmlには、インターフェイスの使用方法に関する十分な文書があります。

ちなみに、deflate()が出力待ちの出力量を知ることができるzlib(1.2.6)の最新バージョンにdeflatePending()関数があります。

+0

この詳細な回答ありがとうございました! 'deflate()'への次の呼び出しに必要な出力バッファを予測するために、 'deflatePending()'によって報告されたサイズと 'deflateBound()'によって返された値を追加することを考えました。それは@EugenRieckの提案に似ています。しかし、私が理解しているように、 'deflateBound()'は圧縮される入力全体のサイズが渡されたときにのみ動作することが文書化されているので、これは良い考えではありません。私。 'deflateBound()'は入力塊のために働くとは書かれていません。 – feklee

+1

deflateBound()は、前のすべての入力が圧縮されて出力された場合にのみ、入力の塊に対して機能します。これは、Z_NO_FLUSH以外のフラッシュオプションを使用し、以前の呼び出しですべての出力を消費することによってのみ保証されます。この場合、deflatePending()は、Z_BLOCKまたはZ_PARTIAL_FLUSHが使用されている場合に便利です。なぜなら、それらが数ビット残っている可能性があるからです。 Z_NO_FLUSHを使用している場合、deflateBound()+ deflatePending()には前のdeflate()呼び出しで消費された入力のサイズですが、まだ圧縮されずに出力されている3番目の部分が欠落しています。 –

2

は、私は、)(デフレート全体のショーを無効flush_pending()の使用をトレース

/* ========================================================================= 
* Flush as much pending output as possible. All deflate() output goes 
* through this function so some applications may wish to modify it 
* to avoid allocating a large strm->next_out buffer and copying into it. 
* (See also read_buf()). 
*/ 
local void flush_pending(strm) 
    z_streamp strm; 
{ 
    unsigned len = strm->state->pending; 
... 

の上に落ちた必要なの上限いますストリームの途中の出力バッファが

strm->state->pending + deflateBound(strm, strm->avail_in) 

であり、最初の部分が以前の呼び出しからパイプに残っているデータを占めるdeflate()すると、2番目の部分はまだ処理されていない長さavail_inのデータになります。

+0

あなたは今削除された回答のコメントに間違いありませんでした。私は内部の状態を忘れていた。好奇心の念から、私は迅速なテストで収縮する最初の呼び出しの後にその保留中の値を見ました。 avail_inは0、avail_outは2、保留はゼロ(0)でした。保留中のデータの実際の量は反映されていないようです。次にそれをフラッシュするためにdeflateを呼び出して〜8Kを出力にダンプしました。したがって、少なくとも1つの状況では、正確な測定ではない可能性があります。 –

+0

あなたは、 'strm-> state-> pending'はパイプ*にまだ残っているデータのサイズであると言います。私が正しく理解すると、未知の上限に達するまで、 'deflate()'を呼び出すたびにこのサイズが増えます。そして、この上限は正確に私が探しているものです。それでは、どのように役立ちますか?何か不足していますか? – feklee

+0

私は、deflate()にstrm-> state-> pending + deflateBound(strm、strm-> avail_in)のバッファを与えた場合、バッファ領域を使い果たすことはないということを意味します。私は参照してください –