Zstd: 圧縮コンテキストが定期的に破棄される場合の圧縮率の向上

作成日 2019年07月08日  ·  3コメント  ·  ソース: facebook/zstd

圧縮コンテキストが再利用されていない場合、一貫してわずかに優れた圧縮率が得られます。
ZSTD圧縮コンテキストを作成してから、ZSTD_compressCCtxを呼び出すループで、毎回1MBのバッファーにデータを提供しています。 プロセスの最後に、圧縮コンテキストが解放されます。
次の1MBバッファーの圧縮に進む前に、圧縮コンテキストを解放して新しいコンテキストを作成すると、出力ファイルのサイズは一貫して約1%小さくなります。
もう1つの興味深い事実は、データで2MBの入力バッファーを使用している場合、1MBの入力バッファーと比較して、圧縮率が約1〜1.5%向上することです。
私のユースケースでは、メモリリソースによる制限はありません。
質問

  • データの大きなチャンクを圧縮する間に圧縮コンテキストを破棄することをお勧めしますか?

    • 推奨される最適な入力バッファサイズは何ですか(つまり、バッファサイズを小さくすると圧縮率が低下しますが、バッファサイズを大きくしても圧縮率は向上しません)。

    • zstdに「必要なだけメモリを使用しますが、圧縮率や速度を向上させてください」と伝える方法

    • それは本当にメモリに制約のあるユースケースにのみ適したコンテキストでのストリーミング圧縮ですか? 十分なメモリがある場合は、大きな(> 1MB)バッファを個別に圧縮する方が良いですか?

question

全てのコメント3件

こんにちは@scherepanov

この結果は驚くべきものです。
同じ入力と同じ圧縮レベルでZSTD_compressCCtx()を使用すると、コンテキストが再利用されるかどうかは(圧縮率の観点から)重要ではありません。 コンテキストを再利用することの唯一の影響は、割り当てと初期化の時間を節約することです。それだけです。 それが圧縮率に影響を与える場合、それは奇妙であり、おそらく間違っています。

可能であれば、このシナリオを再現したいと思います。 どのバージョンを使用していますか?

データの大きなチャンクを圧縮する間に圧縮コンテキストを破棄することをお勧めしますか?

コンテキストを破棄する必要はありません。
唯一の「良い」理由は、コードを単純化することです。
しかし、パフォーマンスの観点からは、それは有益であり、マイナス面ではないはずです。

推奨される最適な入力バッファサイズ

これは非常に状況に応じたものです。 「普遍的な」しきい値はありません。
一般的に言えば、ウィンドウサイズの8倍を超えると、チャンクサイズを増やすことの価値はますます低くなります。
ただし、ウィンドウサイズは、圧縮レベルに応じて動的な値です。
512 KB(レベル1)から8 MB(レベル19)までさまざまです。

zstdに「必要なだけメモリを使用しますが、圧縮率を向上させてください」と伝える方法

レベル19はこの種のものであると思われます

および/または速度」

レベル4は一般的にこの種です。圧縮はかなり高速ですが、大量のメモリを使用します。 それは私が考えることができる最も近いものです。

それは本当にメモリに制約のあるユースケースにのみ適したコンテキストでのストリーミング圧縮ですか? 十分なメモリがある場合は、大きな(> 1MB)バッファを個別に圧縮する方が良いですか?

独立したチャンクを1回のパス( ZSTD_compressCCtx()およびZSTD_decompressDCtx() )で圧縮/解凍するのは非常に簡単で、可能な限り効率的です。 あなたがそれをすることができれば、それは好ましいです。 ストリーミングモードは、それに加えて多くの複雑さを追加します。 複雑さは主に内部に隠されていますが、主なアイデアは、単純なワンパス圧縮または解凍よりも優れている/高速であることはできないということです。

非常に明確な答えをありがとう。
さまざまな圧縮率を、データのさまざまな順序にトレースしました。 はい、あなたが言ったように、コンテキストを再利用することと破棄することは違いを生みません。 申し訳ありませんが、質問をする前に、もっと注意して調査する必要があります。
あなたのコメントは非常に明確で非常に説明的です。 本当にドキュメントに追加する必要があると思います。 特にストリーミングと非ストリーミングの違いについては、辞書をより適切に作成できるため、ストリーミングの方が効率的であると常に考えられていました(ただし、ファイル内のデータが変更されたときに辞書をどのように変更するかは明確ではありません)。 ストリーミングは「ブロックベース」の圧縮とほとんど同じであることを明確に理解することが非常に重要です。 一方、チャンクサイズを自動的に処理するため、ストリーミングの方が効率的です。 デフォルトの圧縮レベル3で1MBのチャンクサイズを使用していますが、より良い圧縮を得るには不十分のようです。 この観点から、チャンクサイズをより最適に決定するため、ストリーミングは圧縮率でより効率的になります。 (これは正しいです???)

ストリーミングは「ブロックベース」の圧縮とほとんど同じです

それは完全に「同じ」ではありません。

入力データをチャンクに分割し、それらを個別にZSTD_compressCCtx()に渡すと、複数の独立した圧縮チャンクになります。 圧縮された各チャンクは、独立した_frame_です。 各フレームは独立しているため、任意の順序で解凍できます。

同じデータをZSTD_compressStream() 、チャンクせずに単一のストリームに送信すると、最終的には_単一フレーム_になります。 内部的には、フレームはブロックにカットされていますが、ブロックは独立していないため、それは問題ではありません。 フレームの任意の部分をデコードするには、最初からすべてをデコードする必要があります。

理論的には、単一のフレームは複数の独立したフレームよりも圧縮率が高いはずです。 これは、データを複数の独立したチャンクに分割すると、各チャンクの開始時に圧縮の機会が失われるためです。
ただし、高速モードは単に「確率的」コンプレッサーであり、高速で実行するために急いで賭けます。 すべての機会が等しいわけではなく、場合によっては、1つの機会を選択するだけで、後のより良い機会が隠されてしまいます。 これは非常にデータ固有です。
したがって、まれに、データを独立したチャンクに分割すると、単一のストリームと競合する場合があります。
しかし、私はそれには賭けません。 ほとんどの場合、ほんの少しでも、単一のストリームが勝つはずです。

このページは役に立ちましたか?
0 / 5 - 0 評価