デルタ符号化とは、連続するデータ間の差分(デルタ)を、完全なファイルではなく、差分データとして保存または送信する方法です。より一般的には、これはデータ差分化と呼ばれます。デルタ符号化は、特に変更履歴のアーカイブが必要な場合(例えば、バージョン管理ソフトウェアなど)には、デルタ圧縮と呼ばれることもあります。
差分は「デルタ」または「diff」と呼ばれる個別のファイルに記録されます。差分が小さい場合(例えば、大きな文書内の数語の変更や、大きな表内の数レコードの変更など)、デルタ符号化によってデータの冗長性が大幅に削減されます。一意のデルタの集合は、符号化されていない同等のデルタの集合よりも大幅にスペース効率が高くなります。
論理的な観点から言えば、2 つのデータ値の差は、一方の値から他方の値を得るために必要な情報である(相対エントロピーを参照) 。同一の値間の差(何らかの等価性の下で)は、しばしばあるいは中立的な要素。
コンピュータ科学および情報理論において、データ差分法または差分圧縮法とは、ソースデータとターゲットデータという2つのデータセット間の差異を技術的に記述する手法である。正式には、データ差分アルゴリズムは、入力としてソースデータとターゲットデータを受け取り、ソースデータと差分データがあればターゲットデータを再構築できるような差分データを生成する(ソースデータを差分データで「パッチ適用」してターゲットデータを生成する)。
おそらく最も単純な例は、バイト値を値そのものではなく、連続する値間の差分(デルタ)として格納することです。つまり、私たちは保管しますこれにより、隣接するサンプルが相関している場合の値の分散(範囲)が小さくなり、同じデータに対してより少ないビット使用量が可能になります。IFF 8SVXサウンド フォーマットは 、圧縮を適用する前に、生のサウンド データにこのエンコーディングを適用します。8 ビットのサウンドサンプルすべてがデルタ エンコードでより良く圧縮されるわけではなく、16 ビット以上のサンプルではデルタ エンコーディングの有用性はさらに小さくなります。そのため、圧縮アルゴリズムは、圧縮がデルタ エンコードなしよりも優れている場合にのみデルタ エンコードを選択することがよくあります。ただし、ビデオ圧縮では、デルタ フレームはフレーム サイズを大幅に削減でき、事実上すべてのビデオ圧縮コーデックで使用されています。これらのフレームには、異なるタイプのデルタ計算が必要です。
数値の差分は、上記の例に示すように、減算によって簡単に定義できます。算術演算の性質により、数値の差分は対称です。つまり、後者の値が前者より小さい場合、前者の値は前者より小さくなります。が既知であれば、デルタを適用することが可能です逆方向に操作して前の値を取得する。
数値的な「デルタのデルタ」を生成することも可能です。これは、基となるデータが次のようなプロセスによって生成される場合に役立ちます。2次デルタではデータがゼロの列に平坦化されてしまうため、これは問題です。タイムスタンプはしばしばこのように動作します。[ 1 ]実際のデータでは、さらに高次のデルタも役立つ場合があります。たとえば、時間経過に伴う航法衛星までの測定距離(擬似距離)は、3次デルタ、つまり「デルタのデルタのデルタ」を使用して最もよく圧縮されます。[ 2 ]
減算に加えて、ビットごとの排他的論理和(XOR) も対称的な差分を生成します。時系列データベースでは、XOR 演算が浮動小数点数間の差分としてよく使用されます。これは、XOR 演算によって、ほとんどがゼロビットで構成される圧縮しやすい差分が生成されるためです。[ 1 ]
もう1つのバリエーションは、デルタ演算に使用される要素間の距離を変更することです。シーケンスで「距離2」のデルタは、これは、 xzの「デルタ」フィルターで確認できます。[ 3 ]
以下のC言語コードは、文字シーケンスに対して単純な形式のデルタ符号化と復号化を実行します。
void encode ( uint8_t buffer [], size_t length ) { uint8_t last = 0 ; for ( size_t i = 0 ; i < length ; ++ i ) { uint8_t current = buffer [ i ]; buffer [ i ] = current - last ; last = current ; } }void decode ( uint8_t buffer [], size_t length ) { uint8_t last = 0 ; for ( size_t i = 0 ; i < length ; ++ i ) { uint8_t delta = buffer [ i ]; buffer [ i ] = delta + last ; last = buffer [ i ]; } }値のシーケンスまたはセット(文字列や画像など)間の差分については、デルタは対称デルタと有向デルタの2つの方法で定義できます。2つのセット間の対称デルタには、可逆性を確保するために十分な情報が含まれています。
2 つのシーケンスの差分も同様に定義されますが、追加と削除の位置を示す情報が追加されます。コンピュータの実装では、diff コマンドの出力(デフォルト、統合、コンテキストモード) にその例が示されます。出力は「位置」という形式の命令です。(古いコンテンツを)(新しいコンテンツ)に置き換えます。
方向付きデルタ(変更とも呼ばれる)は、(基本的な)変更操作のシーケンスであり、、別のものを生み出す、(データベースのトランザクションログとの対応関係に注目してください)。コンピュータ実装では、通常、2 つのコマンドを持つ言語の形式をとります。そして、リテラルデータを書き込みます。例としては、スクリプト編集モードでdiffコマンドを実行したときの出力が挙げられます。
文字列の接頭辞または接尾辞の差分を符号化するデルタ符号化の変形は、インクリメンタル符号化と呼ばれます。これは、辞書の単語リストのように、文字列間の差分が小さいソート済みリストに特に効果的です。
エンコードされるデータの性質は、特定の圧縮アルゴリズムの有効性に影響を与える。
デルタ符号化は、データの変動が小さいか一定である場合に最も効果を発揮します。ソートされていないデータセットの場合、この方法ではほとんど、あるいは全く圧縮できない可能性があります。
ネットワーク上でデルタ符号化されたデータ転送を行う場合、通信チャネルの両端にファイルのコピーが1つしか存在しない状況では、ファイルのどの部分が以前のバージョンから変更されたかを検出するために、特別なエラー制御コードが使用されます。例えば、rsyncはMark Adlerのadler-32チェックサムに基づくローリングチェックサムアルゴリズムを使用しています。
データ差分の最もよく知られた例の 1 つはdiffユーティリティで、テキスト ファイル(および一部の実装ではバイナリ ファイル)の行ごとの差分を生成し、汎用差分ツールとなっています。一般的なバイナリ ファイルの差分はデルタ エンコーディングの範疇に属し、広く使用されている例としてrsyncで使用されているアルゴリズムがあります。標準化された汎用差分フォーマットはVCDIFFで、 Xdeltaバージョン 3などのユーティリティで実装されています。高効率 (小さなパッチ ファイル) の差分プログラムは bsdiff で、生成された差分に対して最終圧縮ステップとしてbzip2 を使用します。 [ 4 ]
デルタアップデートとは、ソフトウェアのコードのうち、新規に追加された部分、または以前の状態から変更された部分のみをユーザーがダウンロードすれば済むソフトウェアアップデートであり、プログラム全体をダウンロードする必要はありません。デルタアップデートを使用することで、時間とコンピューティング帯域幅を大幅に節約できます。「デルタ」という名前は、数学で変化を表すためにギリシャ文字のデルタ(Δまたはδ)が使われることに由来します。[ 5 ]
この基盤となる技術は、バイナリ差分圧縮とも呼ばれます。いずれの場合も、旧バージョンとダウンロードされた差分データを組み合わせて新バージョンを復元します。差分データの生成に使用される技術の詳細については、「データ差分」を参照してください。
デルタエンコーディングの使用例としては、 RFC 3229「HTTPにおけるデルタエンコーディング」が挙げられます。このRFCでは、HTTPサーバーは更新されたWebページをバージョン間の差分(デルタ)の形で送信できるようにすべきだと提案しています。これは、ほとんどのページは繰り返し完全に書き換えられるのではなく、時間の経過とともにゆっくりと変化するため、インターネットトラフィックを削減するはずです。
この文書では、デルタエンコーディングをHTTP/1.1の互換性のある拡張機能としてサポートする方法について説明します。
HTTP(ハイパーテキスト転送プロトコル)リクエストの多くは、クライアントが既にキャッシュエントリを持っているリソースの、わずかに変更されたインスタンスの取得を引き起こします。研究によると、このような変更更新は頻繁に発生し、変更内容は通常、実際のエンティティよりもはるかに小さいことがわかっています。このような場合、HTTPはリソースの新しいインスタンス全体ではなく、変更内容の最小限の説明を転送できれば、ネットワーク帯域幅をより効率的に利用できます。
[...] この文書の後半で説明する「インスタンス操作」フレームワークを使用してrsyncをサポートできる可能性があると考えていますが、詳細はまだ検討されていません。
提案されたrsyncベースのフレームワークは、HTTPプロキシのペアとしてrproxyシステムに実装されました。 [ 6 ]基本的なvcdiffベースの実装と同様に、どちらのシステムもほとんど使用されていません。
差分コピーは、以前のバージョンがコピー先の場所に存在する場合に、部分的に変更されたファイルを高速にコピーする方法です。差分コピーでは、ファイルの変更された部分のみがコピーされます。これは通常、バックアップまたはファイルコピーソフトウェアで使用され、多くの場合、プライベートネットワークまたはインターネットを介してコンピュータ間でコピーする際の帯域幅を節約します。注目すべきオープンソースの例の 1 つはrsyncです。[ 7 ] [ 8 ] [ 9 ]
多くのオンラインバックアップサービスは、ユーザーに以前のバックアップから同じファイルの以前のバージョンを提供するために、この方法(一般的には単にデルタと呼ばれる)を採用しています。これにより、異なるバージョンとして保存する必要のあるデータ量(変更されたファイルの各バージョン全体をユーザーがアクセスできるようにする必要があるため)だけでなく、更新された各ファイルのアップロード(場合によってはダウンロード)にかかるコスト(ファイル全体ではなく、より小さなデルタのみを使用すればよいため)も削減されます。
大規模なソフトウェアパッケージの場合、バージョン間で変更されるデータは通常ごくわずかです。多くのベンダーは、時間と帯域幅を節約するために差分転送方式を採用しています。
Diffはファイル比較プログラムで、主にテキストファイルで使用されます。デフォルトでは、可逆的な対称差分を生成します。ソフトウェアパッチに使用される2つのフォーマット、contextとunifiedは、行番号のずれを許容するための追加のコンテキスト行を提供します。
Git ソースコード管理システムは、補助的な「git repack」操作でデルタ圧縮を採用しています。リポジトリ内のまだデルタ圧縮されていないオブジェクト(「ルーズオブジェクト」)は、ヒューリスティックに選択された他のすべてのオブジェクトのサブセットと比較され、共通データと差分が「パックファイル」に連結され、従来の方法で圧縮されます。ソースファイルやデータファイルがコミット間で段階的に変更される一般的な使用例では、これにより大幅な容量削減が可能になります。リパック操作は通常、「git gc」[ 10 ]プロセスの一部として実行され、ルーズオブジェクトまたはパックファイルの数が設定されたしきい値を超えると自動的にトリガーされます。
このフォーマットは、Git ドキュメントの pack-format ページに記載されています。これは、指向性デルタを実装しています。[ 11 ]
指向性デルタ符号化の一般的なフォーマットの一つに、 RFC 3284で規定されているVCDIFFがある。フリーソフトウェアによる実装としては、Xdeltaやopen-vcdiffなどが挙げられる。
汎用差分フォーマット(GDIFF)は、別の指向性デルタ符号化フォーマットです。これは1997年にW3Cに提出されました。 [ 12 ]多くの場合、VCDIFFはGDIFFよりも圧縮率が優れています。
Bsdiff はサフィックスソートを使用するバイナリ差分プログラムです。ポインタアドレスの変更が多い実行ファイルの場合、VCDIFF タイプの「コピーとリテラル」エンコーディングよりも優れたパフォーマンスを発揮します。その目的は、アセンブリコードを解析することなく (Google の Courgette のように) 小さな差分を生成する方法を見つけることです。Bsdiff は、エラーのある「コピー」マッチを許可し、バイトごとの差分の追加「追加」配列を使用してエラーを修正することでこれを実現します。この配列は、オフセットの変更に対してほとんどがゼロまたは繰り返し値であるため、圧縮後には小さなスペースしか占有しません。[ 13 ]
bsdiff は差分更新に役立ちます。Google は Chromium と Android で bsdiff を使用しています。RPMパッケージマネージャのdeltarpm機能は、ハッシュテーブルを使用してマッチングできる大幅に変更された bsdiff に基づいています。[ 14 ] FreeBSDも更新に bsdiff を使用しています。[ 15 ]
2005年にbsdiff 4.3がリリースされて以来、さまざまな改良や修正が行われてきました。Googleは、各製品向けに複数のバージョンのコードを維持しています。[ 16 ]divsufsort FreeBSDは、主に脆弱性の修正とより高速なサフィックスソートルーチンへの切り替えなど、Googleの互換性のある変更の多くを取り入れています。 [ 17 ] Debianは、このプログラムに一連のパフォーマンス調整を加えています。[ 18 ]
ddelta は、Debian のデルタ アップデートで使用するために提案された bsdiff の書き直しです。他の効率改善の中でも、メモリと CPU コストを削減するためにスライディング ウィンドウを使用しています。[ 19 ]
データ差分処理における主な懸念事項は、使いやすさとスペース効率(パッチサイズ)です。ソースとパッチからターゲットを再構築したいだけであれば、ターゲット全体をパッチに含め、ソースを破棄してパッチに含めたターゲットを出力することでパッチを「適用」できます。同様に、ソースとターゲットのサイズが同じであれば、ソースとターゲットをXOR演算することで単純なパッチを作成できます。どちらの場合も、パッチのサイズはターゲットと同じになります。これらの例が示すように、ターゲットの再構築だけが目的であれば、大きなパッチが必要になるものの、これは容易に実現できます。汎用的なバイナリ差分処理における主な懸念事項は、パッチサイズを小さくすることです。
特に構造化データの場合、他にも考慮すべき点があり、その多くは「ユーザビリティ」に関するものです。例えば、2つの文書を比較する場合、どのセクションが変更されたか、あるいはセクションの順序が変わったかを知りたいと思うのが一般的です。つまり、文書がどのように異なるかを理解したいのです。例えば、「ここでは『cat』が『dog』に変更され、13段落目が14段落目に移動されました」といった具合です。また、頑健な差異表示を望む場合もあります。例えば、2つの文書AとBの13段落目が異なる場合、Aの7段落目を変更した場合でも、このパッチを適用できるようにしたいと考えるかもしれません。これの一例がdiffコマンドです。diffコマンドはどの行が変更されたかを示し、コンテキスト形式によって頑健性と人間による読みやすさが向上します。
その他の懸念事項としては、データ圧縮などの計算効率が挙げられます。小さなパッチを見つけるには、非常に多くの時間とメモリが必要になる場合があります。比較対象のデータやその他の制約について知識がある場合に最良の結果が得られます。diffは行指向のテキスト ファイル、特にソース コード用に設計されており、これらに最適です。rsyncアルゴリズムは、ソースとターゲットがネットワークを介して互いに離れており、通信が遅いことを前提として使用されるため、送信する必要のあるデータを最小限に抑えます。また、Google Chromeのアップデートでは、プログラムのデータのアーカイブ形式と実行形式に合わせてカスタマイズされたアルゴリズムが使用されます。[ 20 ] [ 21 ]
データ圧縮は、データ差分法の特殊なケースと見なすことができます[ 22 ] [ 23 ]。データ差分法は、ソースとターゲットが与えられた場合に差分を生成することであり、パッチングはソースと差分が与えられた場合にターゲットを生成することであり、データ圧縮は、ターゲットが与えられた場合に圧縮ファイルを生成することであり、解凍は、圧縮ファイルのみが与えられた場合にターゲットを生成することです。したがって、データ圧縮は、空のソースデータを用いたデータ差分法と見なすことができ、圧縮ファイルは「何もないことからの差分」に対応します。これは、絶対エントロピー(データ圧縮に対応)を、初期データがない相対エントロピー(データ差分法に対応)の特殊なケースと見なすことと同じです。
関連性を強調したい場合は、データ差分を指す用語として差分圧縮という用語を用いることができる。
両分野の用語を相互に翻訳する辞書は以下のとおりです。
デルタは数学において「変化」または「変化」を意味する。