日本語 ▾ トピック ▾ 最新バージョン ▾ multi-pack-index は 2.47.0 で最終更新されました

Git オブジェクトディレクトリには、パックファイル (末尾が ".pack") とパックインデックス (末尾が ".idx") を含む pack ディレクトリが含まれています。パックインデックスは、オブジェクトを検索し、パック内のオフセットに移動する方法を提供しますが、これらはパックファイルと対になっていなければなりません。このペアリングはファイル名に依存しており、パックインデックスはパックファイルとサフィックスのみが異なります。パックインデックスはパックファイルごとの高速な検索を提供しますが、パックファイルの数が増加するとこのパフォーマンスは低下します。これは、省略形がすべてのパックファイルを検査する必要があり、最近使用したパックファイルでミスが発生する可能性が高くなるためです。一部の大きなリポジトリでは、ストレージスペースや過剰な再パック時間のため、単一のパックファイルに再パックすることは実現不可能です。

multi-pack-index (略して MIDX) は、複数のパックファイルにわたるオブジェクトとそのオフセットのリストを保存します。これには以下が含まれます。

  • パックファイル名のリスト。

  • オブジェクト ID のソート済みリスト。

  • i 番目のオブジェクト ID のメタデータリスト。これには以下が含まれます。

    • j 番目のパックファイルを参照する値 j。

    • オブジェクトの j 番目のパックファイル内のオフセット。

  • 大きなオフセットが必要な場合、バージョン 2 のパックインデックスに似た別の大きなオフセットのリストを使用します。

    • 疑似パック順序のオブジェクトのオプションリスト (MIDX ビットマップで使用されます)。

したがって、任意の数のパックファイルに対して O(log N) の検索時間を提供できます。

設計の詳細

  • MIDX は .git/objects/pack ディレクトリ内の multi-pack-index という名前のファイルに保存されます。これは代替のパックディレクトリに保存することもできます。このファイルは、その同じディレクトリ内のパックファイルのみを参照します。

  • MIDX ファイルを使用するには、core.multiPackIndex の設定がオンになっている必要があります (これはデフォルトです)。`false` に設定すると、MIDX ファイルが存在しても Git はそれを読み込まなくなります。

  • ファイル形式にはオブジェクト ID ハッシュ関数のパラメータが含まれているため、将来のハッシュアルゴリズムの変更によって形式の変更が必要になることはありません。

  • MIDX はオブジェクト ID ごとに 1 つのレコードのみを保持します。オブジェクトが複数のパックファイルに存在する場合、MIDX は優先されるパックファイル内のコピーを選択し、それ以外の場合は最も最近変更されたパックファイルから選択します。

  • パックディレクトリ内に MIDX に登録されていないパックファイルが存在する場合、それらのパックファイルは `packed_git` リストと `packed_git_mru` キャッシュにロードされます。

  • パックインデックス (.idx ファイル) はパックディレクトリに残されるため、MIDX ファイルを削除したり、core.midx を false に設定したり、情報を失うことなくダウングレードしたりできます。

  • MIDX ファイル形式は、オプションのデータを追加できるチャンクベースのアプローチ (コミットグラフファイルに類似) を採用しています。

インクリメンタルマルチパックインデックス

リポジトリのサイズが大きくなるにつれて、すべてのパックファイルを含むマルチパックインデックス (MIDX) を書き込むコストが高くなります。これに対応するため、「インクリメンタルマルチパックインデックス」機能では、マルチパックインデックスの「チェーン」を組み合わせることができます。

チェーンの各個々のコンポーネントは、少数のパックファイルのみを含んでいればよいです。チェーンに追加してもチェーンの以前の部分が無効になることはないため、リポジトリは MIDX チェーンの各レイヤーに含まれるパックの数を決定することで、MIDX チェーンの更新に費やされる時間を制御できます。

設計状況

現在、インクリメンタルマルチパックインデックス機能には、2つの重要なコンポーネントが不足しています。

  • MIDX チェーンの以前の部分を書き換える機能 (すなわち、隣接するいくつかの MIDX レイヤーのコレクションを単一の MIDX に「圧縮」する機能)。現在、MIDX チェーンを縮小する唯一のサポートされている方法は、`--split` フラグなしでチェーン全体を最初から書き換えることです。

    この機能を実装する上で根本的な制限はありません。複雑さを軽減するために初期実装からは省略されていますが、後で追加される予定です。

  • 到達可能性ビットマップのサポート。従来の単一 MIDX 実装は到達可能性ビットマップをサポートしています (詳細については、gitformat-pack[5] の「multi-pack-index reverse indexes」と題されたセクションを参照してください)。

    上記と同様に、インクリメンタル MIDX 形式を拡張して到達可能性ビットマップをサポートする上で根本的な制限はありません。以下の設計はこれを特に考慮しており、到達可能性ビットマップのサポートは将来のパッチシリーズで追加される予定です。上記と同じ理由で、現在の実装からは省略されています。

    要するに、インクリメンタル MIDX 機能で到達可能性ビットマップをサポートするために、疑似パック順序の概念はインクリメンタル MIDX チェーンの各レイヤーにわたって拡張され、連結された疑似パック順序を形成します。この連結はチェーン自体と同じ順序で行われます (言い換えれば、`{$H1, $H2, $H3}` というチェーンの連結された疑似パック順序は、$H1 の疑似パック順序に続き、$H2 の疑似パック順序、さらに $H3 の疑似パック順序が続くことになります)。

    その後、レイアウトが拡張され、インクリメンタル MIDX チェーンの各レイヤーが `*.bitmap` を書き込めるようになります。各レイヤーのビットマップ内のオブジェクトは、チェーンの以前のレイヤーのオブジェクト数によってオフセットされます。

ファイルレイアウト

`$GIT_DIR/objects/pack` に単一の `multi-pack-index` ファイル (オプションの `.rev` および `.bitmap` 拡張子付き) を保存する代わりに、インクリメンタル MIDX は以下のレイアウトで保存されます。

$GIT_DIR/objects/pack/multi-pack-index.d/
$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-chain
$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-$H1.midx
$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-$H2.midx
$GIT_DIR/objects/pack/multi-pack-index.d/multi-pack-index-$H3.midx

`multi-pack-index-chain` ファイルには、チェーン内のインクリメンタル MIDX ファイルのリストが順に含まれます。上記の例は、`multi-pack-index-chain` ファイルに以下の行が含まれるチェーンを示しています。

$H1
$H2
$H3

`multi-pack-index-$H1.midx` ファイルにはマルチパックインデックスチェーンの最初のレイヤーが含まれ、`multi-pack-index-$H2.midx` ファイルにはチェーンの2番目のレイヤーが含まれる、といった具合です。

インクリメンタル MIDX と非インクリメンタル MIDX の両方が存在する場合、非インクリメンタル MIDX が常に最初に読み込まれます。

インクリメンタル MIDX のオブジェクト位置

元のマルチパックインデックス設計では、リポジトリの単一のマルチパックインデックス内での辞書式順序 (オブジェクト ID 順) による位置によってオブジェクトを参照します。インクリメンタルマルチパックインデックス設計では、MIDX チェーン内の各コンポーネント間の連結された辞書式順序におけるインデックスによってオブジェクトを参照します。

もし `objects_nr()` が特定の MIDX レイヤー内のオブジェクト数を返す関数である場合、たとえば $H3 内の辞書式順序 `i` のオブジェクトのインデックスは次のように定義されます。

objects_nr($H2) + objects_nr($H1) + i

(C 言語の実装では、これはしばしば `i + m->num_objects_in_base` として計算されます。)

今後の作業

  • マルチパックインデックスは、特に再パックが高価な (非常に大きなリポジトリなど) または予期せぬメンテナンス時間が許容できない (高負荷のビルドマシンなど) 環境において、多数のパックファイルを可能にします。しかし、マルチパックインデックスは毎回完全に書き換えられる必要があります。書き込みを高速にするために、形式をインクリメンタルに拡張できます。大きな「ベース」MIDX ファイルを指す小さな「ティップ」マルチパックインデックスを保存することで、オブジェクト検索に必要な二分探索の数を減らしつつ、書き込みを高速に保つことができます。

  • マルチパックインデックスが「安定したオブジェクト順序」(multi-pack-index が更新されても、特定のハッシュに対して一定の整数を返す関数 Order(hash) = integer) を格納するように拡張された場合、MIDX ビットマップは MIDX とは独立して更新される可能性があります。

  • パックファイルは、初期名を共有しつつ拡張子 ".pack" を ".keep" または ".promisor" に置き換えた空のファイルを使用して「特別」とマークできます。パックファイルに関する情報のフラグを記録するオプションのデータチャンクを multi-pack-index に追加できます。これにより、再パック済み再デルタ化済み などの新しい状態が可能になり、マルチパック環境でのパックのメンテナンスに役立ちます。また、オブジェクトタイプ (コミット、ツリー、ブロブなど) ごとにパックファイルを整理し、このメタデータを利用してメンテナンスを助けることも役立つでしょう。

[0] https://bugs.chromium.org/p/git/issues/detail?id=6 Chromium 作業項目: Multi-Pack Index (MIDX)

[1] https://lore.kernel.org/git/20180107181459.222909-1-dstolee@microsoft.com/ multi-pack-index 機能に関する以前の RFC

[2] https://lore.kernel.org/git/alpine.DEB.2.20.1803091557510.23109@alexmv-linux/ Git Merge 2018 貢献者サミット議事録 (MIDX に関する議論を含む)

scroll-to-top