web-dev-qa-db-ja.com

Gitはどのようにスペースを節約し、同時に高速ですか?

最初の Git チュートリアルを http://blip.tv/play/Aeu2CAI で見ました。

Gitはすべてのファイルのすべてのバージョンをどのように保存しますか?また、コードの最新バージョンのみを保存する Subversion よりもスペースで経済的であるにはどうすればよいですか?

これは圧縮を使用して実行できることは知っていますが、速度が犠牲になりますが、これはGitの方がはるかに高速であることも示しています(ただし、最大になるのは、ほとんどの操作がオフラインであるという事実です)。

だから、私の推測は

  • Gitはデータを広範囲に圧縮します
  • uncompression + worknetwork_fetch + workよりも高速であるため、さらに高速です。

私は正しいですか?近いですか?

37
Lazer

Git clone(フルリポジトリ+チェックアウト)がSubversionでチェックアウトされたソースよりも小さい可能性があることをあなたが尋ねていると思います。それとも何か他の意味ですか?

この質問はコメントで答えられます


リポジトリサイズ

まず、チェックアウト(作業バージョン)に沿って、Subversionが元のコピー(最後のバージョン)をそれらの.svnサブディレクトリに保存することを考慮に入れる必要があります。元のコピーはSubversionに圧縮されずに保存されます。

次に、gitは次の手法を使用してリポジトリを小さくします。

  • ファイルの各バージョンは1回だけ保存されます。これは、10のリビジョン(10のコミット)でいくつかのファイルの2つの異なるバージョンしかない場合、gitは10ではなくそれらの2つのバージョンのみを保存することを意味します。
  • オブジェクト(およびデルタ、以下を参照)は圧縮されて保存されます。プログラミングで使用されるテキストファイルは非常によく圧縮されます(元のサイズの約60%、または圧縮によるサイズの40%の縮小)
  • 再パック後、他のバージョンとの違いとして、オブジェクトは削除された形式で保存されます。さらに、gitは、デルタが主に削除で構成されるようにデルタチェーンを順序付けようとします(ファイルを成長させる通常の場合、最新の順序になります)。 IIRCデルタも圧縮されます。

パフォーマンス(操作速度)

まず、ネットワークを含む操作は、ローカル操作よりもはるかに遅くなります。したがって、たとえば、作業領域の現在の状態を他のバージョンと比較したり、ログ(履歴)を取得したりします。これは、Subversionではネットワーク接続とネットワーク転送を含み、Gitではローカル操作です。もちろんSubversionではよりもはるかに遅くなります。 Gitで。ところで。これは、Subversionとの間だけでなく、centralizedバージョン管理システム(クライアントサーバーワークフローを使用)とdistributedバージョン管理システム(ピアツーピアワークフローを使用)の違いです。ギット。

第二に、私が正しく理解していれば、今日の制限はCPUではなくIO(ディスクアクセス)です。したがって、圧縮(およびメモリ内でmmapできること)は、データを解凍する必要があることによる損失を克服します。

第三に、Gitはパフォーマンスを念頭に置いて設計されました(例: GitHistory Git Wikiのページを参照):

  • インデックスはファイルの統計情報を格納し、Gitはそれを使用して、ファイルが変更されたかどうかをファイルを調べずに判断します(例:core.trustctime config変数を参照)。
  • 最大デルタ深度はpack.depthに制限されており、デフォルトは50です。Gitにはアクセスを高速化するためのデルタキャッシュがあります。 packfile内のオブジェクトに高速アクセスするための(生成された)packfileインデックスがあります。
  • Gitは、必要のないファイルに触れないように注意します。たとえば、ブランチを切り替えたり、別のバージョンに巻き戻したりすると、Gitは変更されたファイルのみを更新します。この哲学の結果は、Gitが(少なくとも箱から出して)ごくわずかなキーワード拡張しかサポートしないということです。
  • Gitは、外部のdiff /外部マージツールを呼び出す代わりに、 独自のバージョンLibXDiff ライブラリを使用します。現在はdiffとマージにも使用されています。
  • Gitはlatencyを最小化しようとします。これは、良好な知覚パフォーマンスを意味します。たとえば、「git log」の最初のページをできるだけ速く出力し、完全な履歴の生成に時間がかかる場合でも、ほぼすぐに表示されます。完全な履歴が生成されるのを待たずに表示します。
  • 新しい変更をフェッチするとき、Gitはサーバーと共通のオブジェクトをチェックし、(圧縮された)差異のみをシンパックファイルの形式で送信します。確かに、Subversionは更新時に違いのみを送信できます(またはおそらくデフォルトで送信します)。

私はGitハッカーではないので、Gitがパフォーマンスを向上させるために使用するいくつかのテクニックやトリックを見逃した可能性があります。ただし、GitはそのためにPOSIX(メモリマップファイルなど)を多用しているため、MSWindowsではゲインがそれほど大きくない可能性があることに注意してください。

60
Jakub Narębski

完全な答えではありませんが、 これらのコメントAlBlue から)は質問のスペース管理の側面に役立つ可能性があります:

ここで明確にする価値のあることがいくつかあります。

まず、SVNリポジトリよりも大きなGitリポジトリを持つことができます;私はそれが決してそうではなかったことを暗示していなかったと思います。ただし、実際には、一般的に、Gitリポジトリは同等のSVNリポジトリよりもディスク上のスペースを少なくする傾向があります。
あなたが引用していることの1つは、明らかに巨大なApacheの単一のSVNリポジトリです。ただし、git.Apache.orgを確認するだけで、各Apacheプロジェクトに独自のGitリポジトリがあることに注意してください。 本当に必要なのは、like-for-likeの比較です。言い換えると、(abdera)SVNプロジェクトと(abdera)Gitリポジトリのクローンのチェックアウト

git://git.Apache.org/abdera.gitをチェックアウトできました。ディスク上では、28.8Mbを消費しました。
次にSVNバージョンhttp://svn.Apache.org/repos/asf/abdera/Java/trunk/をチェックアウトしたところ、34.3Mbを消費しました。
両方の数値は、RAMスペースに個別にマウントされたパーティションから取得され、引用された数値はディスクから取得されたバイト数でした。
テストの手段としてdu -shを使用する場合、Gitチェックアウトは11Mbで、SVNチェックアウトは17Mbでした。

Apache AbderaのGitバージョンでは、現在のリリースまでのすべてのバージョンの履歴を処理できます。 SVNには、現在チェックアウトされているバージョンのバックアップしかありません。それでも、ディスク上のスペースは少なくて済みます。

どうやって聞いてもいいですか?

ええと、一つには、SVNはもっとたくさんのファイルを作成します。 SVNチェックアウトには2959個のファイルがあります。対応するGitリポジトリには845個のファイルがあります。

次に、SVNには階層の各レベルに.svnフォルダーがありますが、Gitリポジトリには最上位レベルに1つの.gitリポジトリしかありません。これは、(とりわけ)あるディレクトリから別のディレクトリに名前を変更しても、GitではSVNよりも影響が比較的小さいことを意味します。SVNは、とにかくすでに比較的小さな影響しかありません。

第三に、Gitはデータを圧縮オブジェクトとして保存しますが、SVNはそれらを非圧縮コピーとして保存します.svn/text-baseディレクトリに移動すると、(ベース)ファイルの非圧縮コピーが見つかります。
Gitには、すべてのファイル(実際にはすべての履歴)をパックファイルに圧縮するメカニズムがあります。 Abderaの場合、.git/objects/pack/には4.8Mbファイルに単一の.packファイル(すべての履歴を含む)があります。
したがって、リポジトリのサイズは、この場合、現在チェックアウトされているコードと(ほぼ)同じサイズですが、常にそうであるとは思いません。

とにかく、履歴が現在のチェックアウトの合計サイズよりも大きくなる可能性があることは間違いありません。しかし、SVNの動作方法のため、大きな違いを生むには、実際には2倍のサイズに近づく必要があります。それでも、ディスク容量の削減は、とにかくDVCSを使用する主な理由ではありません。それは確かにいくつかの点で利点ですが、それは人々がそれを使用する本当の理由ではありません。

Git(およびHg、およびその他のDVCS)には、(大きな)バイナリがチェックインされてから削除されるという問題があります。これは、バイナリが最新でなくても、リポジトリに表示されてスペースを占有するためです。 。テキスト圧縮は、テキストファイルのこの種の処理を処理しますが、バイナリ圧縮はより問題になります。 (Gitリポジトリのコンテンツを更新できる管理コマンドがありますが、CVSよりもオーバーヘッド/管理コストがわずかに高くなります。gitfilter-branchはsvnadmin dump/filter/loadのようなものです。)


速度の側面については、「 リモート操作でのSubversionに対するgitの速度はどれくらいですか? 」の回答( LinusがGoogleのプレゼンテーションで言った :(ここで言い換えると) )「ネットワークに関係するものはすべてパフォーマンスを殺すだけです」)

そして、 JakubNarębski によって言及された GitBenchmarkドキュメント は、Subversionを直接扱っていなくても、良い追加です。
DVCSでパフォーマンス的に監視する必要のある操作の種類がリストされています。

他のGitベンチマークはこれに記載されています SO質問

14
VonC