
2026/09/17 2:16
オブジェクトストレージ上で Git を実行するには、パックファイルを書き直す必要があります。
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
著者は、標準的なファイルシステム手法による深刻なスケーラビリティ問題に対処するため、オブジェクトストレージを基盤としたオープンソースの Git サーバーを開発した。標準的な Git は高速なローカル読み込みに依存しているが、ネットワークの往復時間は大幅に遅く、既存のソリューションにおけるパフォーマンスのボトルネックとなっている。このレイテンシギャップを克服するために、
.bin および .cue ファイルを用いたカスタムの「Packfile v2」形式が作成された。この形式は、圧縮済み/未圧縮サイズのメタデータ、bin オフセット、長さを正確に含むオブジェクトを順次保存し、zstd 圧縮を使用することで、特定のデータをダウンロードすることなく、HTTP Range リクエストを用いて効率的に取得できるようにしている。以前に試行されたファイルシステムシムを使用したアプローチは、Git パックファイルインデックスが必要とするランダムアクセス操作を効果的に処理できなかったため失敗した。現在のプロトタイプは背景プロセスによるギャップの埋め込みと、コンパクション(圧縮)機能に依存しておらず、パックファイルが永続的に蓄積してしまう点では制限がある。しかしながら、レポジトリへのプッシュで 5 倍の速度向上が見られ、クローン時のクラウドストレージリクエストも大幅に削減できるという顕著な利点を有している。ただし、システムには現在認証、レート制限、パブリック API、およびシーケンシャル保存以外のデルタオブジェクト管理メカニズムが欠如しており、これを直接公開すると重大なセキュリティリスクを引き起こす可能性がある。本文
オブジェクトストレージネイティブな Git サーバー「objgit」の開発と実装
開発の背景とアプローチの変化
近年、複数の企業が Git サーバーの製品化に取り組んでいますが、当プロジェクトではオブジェクトストレージを基盤としたオープンソース Git サーバーの構築を行っています。
-
当初のアプローチ:
- Git をファイルシステム上のリポジトリとして扱うため、オブジェクトストレージ(Tigris)上にファイルシステムシミュレーション層を導入する手法を採用しました。
- しかし、大規模なリポジトリではパフォーマンス低下が著しく現れ、この手法は現実的ではないことが判明しました。
-
転換点:
- Git はデータをすべて「オブジェクト」として管理しているため、オブジェクトストレージのネイティブなオブジェクトとして直接保存するアプローチへと変更しました。
- 従来のパックファイル形式とファイルシステムシムの相互作用がボトルネックとなっていたため、独自の列指向ストア(Columnar Store)ネイティブなパックファイル形式を開発しました。
Git の仕組み:「裸のオブジェクト」とパックファイル
Git とは何か
Git は以下の二つの要素から構成されます。
- オブジェクトの海: 変更内容を実体として保存する部分。
- 参照システム: それらのオブジェクトへの命名参照(ハッシュ値)。
各オブジェクトは、SHA1 ハッシュ値をファイル名とし、内容が圧縮された単なる裸のファイルです。
$ mkdir ~/tmp/gitexample $ git init && git branch -m main $ echo "Hello, blog!" >> hello.txt $ git add . $ git commit -sm "chore: initial commit"
大規模リポジトリでの課題
小規模なリポジトリでは複数の「裸」オブジェクトが存在しますが、Linux カーネルのような巨大なリポジトリ(例:1,000 万個以上のオブジェクト)では以下のような問題が発生します。
- インオード制限: ファイルを個別に作成するとディスク上の inode 数が限界に達します。
- パックファイルへの圧縮: Git はこれを回避するために、複数のオブジェクトを圧縮した**パックファイル(Packfile)**形式へ自動的に変換します。
- コマンド:
git gc
- コマンド:
パックファイルの非適合性
従来の Git の設計は、ローカルストレージと mmap(メモリアドレス空間マッピング) を前提としています。
- ディスクへの書き込み後、即時の読み取りが可能ですが、ネットワークラウンドトリップは少なくとも 10 ミリ秒必要です。
- これを解消するためには、オブジェクトストレージ上のデータに対して
が完了する前にPutObject
を実行する必要があり、これは標準的なオブジェクトストレージの挙動に反します。GetObject
ソリューション:CUE シートと Bin ファイルの導入
CD-ROM の「CUE シート」と.bin ファイルの構造から着想を得た独自の形式を開発しました。これにより、ネットワーク越しでの高効率なデータ取得が可能になります。
構造的特徴
- 二部構成: データ本体(.bin)とメタデータ(.cue)を分離します。
- ランダムアクセスの最適化: HTTP Range リクエストを活用し、必要なオブジェクトだけを抽出できます。
- インデックスエントリに圧縮前・後両方のサイズとファイル内オフセットを格納することで、正確な範囲指定が可能になりました。
Packfiles v2: オブジェクトストレージ・ボガロオ(Boogaloo)
この形式は以下の技術的要素を取り入れています。
- Range リクエストネイティブ対応: バケットから特定のオフセットだけを抽出できる設計です。
- 高速圧縮ライブラリ:
よりも効率的なzlib
を採用しています。zstd - 完全なデルタオブジェクト: デルタ先を参照せず、必要なデータを完全に含む形式です。
形式仕様 (.cue)
バイナリ形式で固定幅レコードを持ち、ヘッダーと記録されたメタデータから構成されます。
| フィールド名 | サイズ | 内容説明 |
|---|---|---|
| Magic (魔術子) | 4 Bytes | |
| Version | 2 Bytes | バージョン番号 |
| Record Size | 2 Bytes | レコードサイズ(固定) |
| Record Count | 8 Bytes | 記録数 |
1 レコードあたりの情報:
- Hash (SHA-1): オブジェクトの一意な識別子 (20 bytes)
- Type: 種類 (blob, tree, commit など)
- Comp: 圧縮アルゴリズム (zstd など)
- Bin Offset: .bin ファイル内でのオフセット位置
- Bin Length: オブジェクトの長さ
- Size: 元のサイズ(非圧縮)
- Delta Base: デルタ先オブジェクトのハッシュ
パフォーマンスベンチマーク結果
独自の形式(New Form)と従来の形式(Old Form)を比較した結果、ネットワークコスト削減が劇的なパフォーマンス向上につながりました。 ※テスト環境: Mac 16 コア / Git v2.55.0 / objgit v1.26.5
プッシュテストの結果
- S3 リクエスト数(プッシュ):
- 既存形式:数千回必要だったものが、数十回に大幅削減。
- Xe/x リポジトリ: 約 300 倍の削減。
- 壁時間(実時間):
- objgit_old (8.7 秒) -> objgit_new (2.2 秒): 4 倍以上高速化。
- Tigris Blog: 5 倍以上高速化。
クローンテストの結果
- S3 リクエスト数(クローン):
- Xe/x リポジトリ: 約 380 倍の削減(旧:6,428 回 -> 新:17 回)。
- 壁時間(実時間):
- objgit_old (11.8 秒) -> objgit_new (2.6 秒): 約 4.5 倍高速化。
- Xe/x: 3m23s -> 54.4s (約 3.7 倍高速化)。
【要約表】クローンテスト詳細
| リポジトリ | 形式 | 壁時間 | S3 要求数 | GET (ファイル別取得) |
|---|---|---|---|---|
| objgit | 旧形式 | 11.8s | 323 回 | 510 |
| objgit | 新形式 | 2.6s | 17 回 | 13 |
| x_old | 旧形式 | 3m23.5s | 6,428 回 | 5,337 |
| x_new | 新形式 | 54.4s | 17 回 | 4 |
| blog | 旧形式 | 2m23.6s | 3,675 回 | 3,155 |
| blog | 新形式 | 1m22s | 158 回 | 1 |
注: 「GET」項目は、パックファイルから個別のオブジェクトを Range リクエストで取得した数を示しています。新形式ではバックグラウンドダウンロードとの競合制御が効率的になっています。
結論と今後の展望
成果と意義
- ネットワークコストの劇的削減: オブジェクトストレージへの API コール数を減らし、レイテンシを大幅に低減しました。
- 運用性の向上: プッシュ/クローン操作が非常にレスポンシブになり、大規模リポジトリでも実用的な速度になりました。
今後の課題と制限事項
- セキュリティ機能の未実装: 現在、認証や認可、レート制限などの機能は実装されていません。インターネット上での公開は推奨されません。
- アーキテクチャ制約: 128 MiB のパックファイルサイズ制限(ダウンロード速度制御のため)がありますが、将来的に Git Large File Storage (LFS) の実装を予定しています。
まとめ
Git のパックファイル形式は、ローカルなファイルシステム上では優れた設計ですが、オブジェクトストレージのようなネットワーク環境では限界があります。 今回考案した「.bin/.cue」形式と列指向ストレージへのネイティブ対応により、この課題を解決し、大規模な Git リポジトリでも高パフォーマンスを実現しました。
引き続きプロジェクトを強化し、認証機能や API の実装などを行っていく予定です。