32

ローカルネットワーク上の古い、低速のホストの仮想マシンに比較的大きなgitリポジトリがあり、最初のクローンを作成するのにかなりの時間がかかるという状況があります。

ravn@bamboo:~/git$ git clone gitosis@gitbox:git00
Initialized empty Git repository in /home/ravn/git/git00/.git/
remote: Counting objects: 89973, done.
remote: Compressing objects: 100% (26745/26745), done.
remote: Total 89973 (delta 50970), reused 85013 (delta 47798)
Receiving objects: 100% (89973/89973), 349.86 MiB | 2.25 MiB/s, done.
Resolving deltas: 100% (50970/50970), done.
Checking out files: 100% (11722/11722), done.
ravn@bamboo:~/git$

gitosisにはgit固有の構成変更はありません。

ネットワークが可能なものまで受信ビットを高速化する方法はありますか?


編集:新しいリポジトリをアップストリームリポジトリに適切に接続する必要があります。私の理解では、これにはクローン作成を行うためにgitが必要であるため、gitの外部でのrawビットコピーは機能しません。

4

6 に答える 6

31

PS。公正警告:

git一般的に非常に速いと考えられています。darcs、bazaar、hgから完全なリポジトリのクローンを作成してみてください(神は禁じられています:TFSまたはsubversion ...)。また、定期的に完全なリポジトリを最初から複製する場合は、とにかく何か間違ったことをしていることになります。あなたはいつでもただgit remote updateそして漸進的な変化を得ることができます。

完全なリポジトリの同期を維持する他のさまざまな方法については、たとえばを参照してください。

(他の関連するSO投稿へのリンクが含まれています)

ダムコピー

前述のように、「ダム」ファイル転送を使用してリポジトリをコピーすることができます。

これは確かに、圧縮、再梱包、デルティファイ、および/またはフィルタリングの時間を無駄にすることはありません。

さらに、あなたは得るでしょう

  • フック
  • 構成(リモート、プッシュブランチ、設定(空白、マージ、エイリアス、ユーザーの詳細など)
  • stashes リモートリポジトリからローカルブランチにstashをフェッチできますか?も参照してください)
  • キャッシュを再利用する
  • reflogs
  • バックアップ(フィルターブランチなどから)およびその他のさまざまなもの(リベース、バイセクトなどからの中間状態)

これはあなたが必要とするものかもしれないし、そうでないかもしれませんが、事実を知っておくのはいいことです


バンドル

Gitクローンは、デフォルトで帯域幅を最適化します。git cloneは、デフォルトではすべてのブランチをミラーリング--mirrorしないため(を参照)、パックファイルをそのままダンプすることは意味がありません(必要以上に送信される可能性があるため)。

本当に多数のクライアントに配布する場合は、バンドルの使用を検討してください。

サーバー側のコストをかけずに高速クローンが必要な場合、gitの方法bundle createです。サーバーが関与しなくても、バンドルを配布できるようになりました。bundle... --all単純なもの以上のものが含まれている場合はgit clone、たとえばbundle ... master音量を下げることを検討してください。

git bundle create snapshot.bundle --all # (or mention specific ref names instead of --all)

代わりにスナップショットバンドルを配布してください。これは両方の長所ですが、もちろん上記の箇条書きからアイテムを取得することはできません。受信側では、

git clone snapshot.bundle myclonedir/

圧縮構成

圧縮を減らす/削除することで、サーバーの負荷を減らすことができます。これらの構成設定を確認してください(pack.compressionサーバーの負荷を下げるのに役立つと思います)

core.compression

デフォルトの圧縮レベルを示す整数-1..9。-1はzlibのデフォルトです。0は圧縮がないことを意味し、1..9はさまざまな速度とサイズのトレードオフであり、9が最も低速です。設定されている場合、これはcore.loosecompressionやpack.compressionなどの他の圧縮変数のデフォルトを提供します。

core.loosecompression

整数-1..9は、パックファイルにないオブジェクトの圧縮レベルを示します。-1はzlibのデフォルトです。0は圧縮がないことを意味し、1..9はさまざまな速度とサイズのトレードオフであり、9が最も低速です。設定されていない場合、デフォルトはcore.compressionです。これが設定されていない場合、デフォルトで1(最高速度)になります。

pack.compression

パックファイル内のオブジェクトの圧縮レベルを示す整数-1..9。-1はzlibのデフォルトです。0は圧縮がないことを意味し、1..9はさまざまな速度とサイズのトレードオフであり、9が最も低速です。設定されていない場合、デフォルトはcore.compressionです。これが設定されていない場合、デフォルトは-1になります。これは、「速度と圧縮の間のデフォルトの妥協点(現在はレベル6と同等)」であるzlibのデフォルトです。

圧縮レベルを変更しても、既存のすべてのオブジェクトが自動的に再圧縮されるわけではないことに注意してください。-Fオプションをgit-repack(1)に渡すことで、強制的に再圧縮できます。

十分なネットワーク帯域幅が与えられると、これ実際にはより高速なクローンになります。それをベンチマークすることにしたときは忘れないでください!git-repack -F

于 2011-11-18T10:23:55.693 に答える
29

深さを使用して、浅いクローンを作成します。

git clone --depth 1 <repository>
于 2014-06-06T16:56:32.773 に答える
7

2014年にgit clone --depth=1 ... 提案されたものはGit2.22で2019年第2四半期に速くなります。
これは、最初の " git clone --depth=..."部分クローン中に、プロミサーオブジェクト(定義上、反対側からフェッチされたすべてのオブジェクト)を列挙してスキップする接続チェックの大部分にサイクルを費やすことは無意味だからです。
これは最適化されています。

clone:部分的なクローンのオブジェクトチェックを高速化します

部分的なクローンの場合、完全な接続チェックを行うのは無駄です。プロミサーオブジェクト(部分クローンの場合はすべて既知のオブジェクト)をスキップし、それらをすべて列挙して接続チェックから除外すると、大規模なリポジトリではかなりの時間がかかる可能性があります。

せいぜい、必要な参照によって参照されるオブジェクトを確実に取得する必要があります。
部分クローンの場合は、これらのオブジェクトが転送されたことを確認してください。

結果:

 Test                          dfa33a2^         dfa33a2
 -------------------------------------------------------------------------
 5600.2: clone without blobs   18.41(22.72+1.09)   6.83(11.65+0.50) -62.9%
 5600.3: checkout of result    1.82(3.24+0.26)     1.84(3.24+0.26) +1.1%

62%高速!


Git 2.26(2020年第1四半期)では、部分クローンでフェッチするときに、不要な接続チェックが無効になりました。

Jonathan Tan()によるcommit 2df1aa2commit 5003377(2020年1月12日)を参照してください。( Junio C Hamanoによってマージされました---コミット8fb3945、2020年2月14日jhowtan
gitster

connected:部分クローンの約束性を検証する

サインオフ-作成者:Jonathan Tan
レビュー者:Jonathan Nieder

コミットdfa33a298d( " clone:部分クローンのオブジェクトチェックを高速化"、2019-04-21、Git v2.22.0-rc0 --merge は、クローン作成時に実行される接続チェックを最適化し--filterて、refsが直接指すオブジェクトの存在のみをチェックします。
しかし、これは十分ではありません。それらはまた、有望なオブジェクトである必要があります。
代わりに、これらのオブジェクトがプロミサーオブジェクトである、つまりプロミザーパックに表示されることを確認して、このチェックをより堅牢にします。

と:

fetch:完全な接続チェックをやめる--filter

サインオフ-作成者:Jonathan Tan
レビュー者:Jonathan Nieder

フィルタが指定されている場合、フェッチしたばかりのパックファイルの内容を完全に接続チェックする必要はありません。参照されるオブジェクトがpromisorオブジェクトであることを確認するだけで済みます。

これにより、多くのpromisorオブジェクトがあるリポジトリへのフェッチが大幅に高速化されます。これは、接続チェック中にすべてのpromisorオブジェクトが列挙され(興味がないことを示すため)、かなりの時間がかかるためです。


また、Git 2.26(2020年第1四半期)では、部分クローンが使用するオブジェクトフィルタリング基準の一部は本質的にオブジェクトトラバーサルに依存しているため、オブジェクト到達可能性ビットマップ機構と部分クローン機構は連携して機能するように準備されていませんでしたが、ビットマップ機構はそのオブジェクトトラバーサルをバイパスするための最適化

しかし、彼らが一緒に働くことができるいくつかのケースがあり、彼らは彼らについて教えられました。

Junio C Hamano()によるcommit 20a5fd8(2020年2月18日)を参照してください。commit 3ab3185 、commit 84243dacommit 4f3bd56commit cc4aa28commit 2aaeb9acommit 6663ae0commit 4eb707ecommit ea047a8commit 608d9c9commit 55cb10fcommit 792f811commit d90fe06(14 Feb 2020)を参照してください551cf8b(2020年2月13日)Jeff King(gitster
peff( Junio C Hamano
によってマージされました---コミット0df82d9、2020年3月2日gitster

pack-bitmapBLOB_LIMIT:フィルタリングを実装する

サインオフ-作成者:Jeff King

以前に実装さBLOB_NONEれたコミットBLOB_LIMITと同様に、結果内のブロブのサイズを確認し、必要に応じてビットの設定を解除することで、フィルターをサポートできます。
これはより少し高価ですBLOB_NONE,が、それでも顕著なスピードアップを生み出します(これらの結果はgit.gitにあります):

Test                                         HEAD~2            HEAD
------------------------------------------------------------------------------------
5310.9:  rev-list count with blob:none       1.80(1.77+0.02)   0.22(0.20+0.02) -87.8%
5310.10: rev-list count with blob:limit=1k   1.99(1.96+0.03)   0.29(0.25+0.03) -85.4%

BLOB_NONE実装は、blobタイプのビットマップをウォークしながらオブジェクトごとに移動する必要があることを除いて、実装と似ています(一致をマスクすることはできませんが、blobごとに個別にサイズを検索する必要があるため) 。
使用の秘訣ctz64()は、から取得されshow_objects_for_type()ます。これは、同様に個々のビットを見つける必要があります(ただし、blobのない大きなチャンクをすばやくスキップしたい)。


Git 2.27(2020年第2四半期)は、「約束された」オブジェクトが約束されたリモートリポジトリからオンデマンドで遅延して取得可能であると想定される部分クローンリポジトリでのコミット祖先接続チェックを簡素化します。

Jonathan Tan()によるcommit 2b98478(2020年3月20日)を参照してください。濱野純雄による合併---コミット0c60105、 20204月22日)jhowtan
gitster

connected:常に部分的なクローン最適化を使用する

サインオフ-作成者:Jonathan Tan
レビュー者:Josh Steadmon

50033772d5 ( " :部分クローンの約束connectedを確認する"、2020-01-30、Git v2.26.0-rc0-バッチ#5にリストされているマージ)を使用すると、高速パス(約束パックのチェック)が次のサブセットを渡すようになります。スローパス(rev-list)>-チェックするすべてのオブジェクトがプロミザーパックで見つかった場合、ファストパスとスローパスの両方が通過します。check_connected()

  • そうしないと、高速パスは確実に通過しません。

これは、低速パスを実行する必要があるときはいつでも高速パスを試行できることを意味します。

高速パスは現在、フラグによって保護されています。したがって、そのフラグを削除します。
また、高速パスを低速パスにフォールバックします。高速パスに障害が発生した場合、障害のあるOIDと残りのすべてのOIDがrev-listに渡されます。

ユーザーに見える主な利点は、部分クローンからのフェッチのパフォーマンスです。具体的には、フェッチの前に行われる接続チェックの高速化です。
特に、私のコンピューター上の部分クローンへのno-opフェッチは、7秒から0.01秒に高速化されました。これは、2df1aa239c( " fetch:完全な接続チェックを忘れるif --filter"、2020-01-30、Git v2.26.0-rc0 --マージがバッチ#5にリストされている)の作業を補完するものであり、前述の50033772d5。そのコミットでは、フェッチ後の接続チェックが高速化されました。

高速パスを追加すると、次の場合にパフォーマンスが低下する可能性があります。

  • 部分クローンまたは部分クローンへのフェッチが失敗した場合、Gitは無駄に実行rev-listされます(フェッチされたものはすべてプロミザーパックに入れられると予想されるため、それが行われなかった場合、rev-listも失敗する可能性があります) 。

  • 部分的なクローンがreceive-packを提供するという(私の意見ではありそうもない)イベントで、receive-packによって実行される接続チェック。

これらのケースは非常にまれであり、この場合のパフォーマンスの低下は十分に小さい(追加のオブジェクトDBアクセス)ため、フラグを回避することの利点がこれらのケースを上回っていると思います。


Git 2.27(2020年第2四半期)では、オブジェクトフィルター " --filter=tree:0"を使用したオブジェクトウォークで、利用可能な場合にパックビットマップを利用できるようになりました。

ジェフキング()によるコミット9639474コミット5bf7f1e(2020年5月4日)を参照してください。Taylor Blau()によるcommit b0a8d48commit 856e12c(2020年5月4日)を 参照してください。濱野純雄による合併---コミット69ae8ff、 20205月13日)peff
ttaylorr
gitster

pack-bitmap.c:'tree:0'フィルタリングをサポート

サインオフ-作成者:Taylor Blau

以前のパッチでは、特定のタイプのすべてのオブジェクトを除外する他のフィルターを簡単に定義できるようにしました。これを使用して、' 'が。に等しい--filter=tree:<n>場合に''フィルターのビットマップレベルのフィルタリングを実装します。n0

n > 0' 'の値の場合、オブジェクトフィルタリング機構は、特定のツリーの深さを決定するために本格的なツリートラバーサルを必要とするため、一般的なケースはビットマップによって支援されません。
同じツリーオブジェクトはコンテキストに応じて異なる深さを持つ可能性があるため、これをキャッシュすることも自明ではありません(たとえば、2つのコミット間でツリーがディレクトリ階層で上に移動された)。

しかし、' n = 0'の場合は助けることができ、このパッチはそうします。
このツリーとカーネルを使用したマスターで実行p5310.11すると、このケースが大幅に役立つことがわかります。

Test                                  master              this tree
--------------------------------------------------------------------------------
5310.11: rev-list count with tree:0   10.68(10.39+0.27)   0.06(0.04+0.01) -99.4%

と:

ジェフキング()によるコミット9639474コミット5bf7f1e(2020年5月4日)を参照してください。Taylor Blau()によるcommit b0a8d48commit 856e12c(2020年5月4日)を 参照してください。濱野純雄による合併---コミット69ae8ff、 20205月13日)peff
ttaylorr
gitster

pack-bitmap:オブジェクトフィルターをフィルイントラバーサルに渡します

サインオフ-作成者:Jeff King
サインオフ-作成者:Taylor Blau

ビットマップトラバーサルでは、コミットがビットマップパックファイルに含まれていないため(たとえば、最後の完全な再パック以降のプッシュまたはコミットのため)、一部のコミットを手動で実行する必要がある場合があります。

オブジェクトフィルターが与えられた場合、それをこのトラバーサルに渡しません。
ビットマップコードには、ビットマップ結果を後処理するための独自のフィルターがあります(ビットマップパックファイルに記載されているオブジェクトをフィルターで除外する必要があるため)。

また、BLOBフィルターでは、これらのフィルターを渡すパフォーマンス上の理由もありませんでした。フィルイントラバーサルでは結果からそれらを除外できますが、ブロブであるかどうかを確認するために各ツリーエントリを歩く必要があるため、そうする時間を節約することはできません。

しかし、ツリーフィルターをサポートするようになったので、節約の機会があります。tree:depth=0フィルタは、ツリー(またはそれらが指すサブツリーやブロブのいずれか)にアクセスしないことがわかっているため、ツリーに完全にアクセスすることを回避できることを意味します。
の新しいテストp5310はこれを示しています(「部分ビットマップ」状態はHEAD~100、その祖先がすべ​​てビットマップパックに含まれているが、そうでHEAD~100..HEADはない状態です)。

結果は次のとおりです(に対して実行linux.git):

Test                                                  HEAD^               HEAD
-------------------------------------------------------------------------------------------------
[...]
5310.16: rev-list with tree filter (partial bitmap)   0.19(0.17+0.02)     0.03(0.02+0.01) -84.2%

節約の絶対数はそれほど多くはありません、最初の親のリンクを100個だけ省略したことに注意してください(linux.gitここのバージョンでは、実際のコミットは894個です)。

より病的なケースでは、ビットマップされていないコミットの割合がはるかに高くなる可能性があります。セットアップに費用がかかるため、perfスクリプトでこのようなケースを作成する必要はありませんでした。これは、節約量をパーセンテージで示すのに十分です。


Git 2.32(Q2 2021)では、特定のオブジェクトが欠落し、遅延して取得できるようにする「プロミザーパック」の処理が最適化されています(少し)。

ジェフ・キング()によるcommit c1fa951commit 45a187ccommit fcc07e9(2021年4月13日)を参照してください。( Junio C Hamanoによってマージされました---コミット13158b9、2021年4月30日peff
gitster

revision:-exclude-promisor-objectsによる解析は避けてください

サインオフ-作成者:Jeff King

--exclude-promisor-objects与えられると、オブジェクトをトラバースする前に、プロミザーパック内のすべてのオブジェクトを反復処理し、それらをUNINTERESTINGおよびSEENとしてマークします。
パックを反復して得たOIDをでオブジェクトに変換しますがparse_object()、これには2つの問題があります。

  • 遅いです。パックファイル内のすべてのオブジェクトのすべてのバイトをzlibで膨らませています(そしてデルタから再構築しています)
  • ツリーバッファが構造体にアタッチされたままになります。つまり、ヒープの使用量が増えて、圧縮されていないすべてのツリーが同時に格納されます。
    これはギガバイトになる可能性があります。

ツリーバッファを解析した後、それらを解放することで、明らかに2番目を修正できます。
しかし、関数がオブジェクトの内容をまったく調べていないことがわかります。私たちが呼び出す唯一の理由は、フラグを設定するためparse_object()の「」が必要なことです。 ここには2つのオプションがあります。struct object

  • を介してオブジェクトタイプだけを検索しoid_object_info()、適切なlookup_foo()関数を呼び出すことができます
  • を呼び出すことができますlookup_unknown_object()。これにより、構造体が得られます(後で、などの呼び出しを介してOBJ_NONE自動変換されます)。object_as_type()lookup_commit()

最初のものは現在のコードに近いですが、各オブジェクトの型を調べるために代償を払っています。
後者はCPUでより効率的ですが、メモリを少し浪費します(「不明な」オブジェクト構造体はすべてのオブジェクトタイプの和集合であるため、一部の構造体は必要以上に大きくなります)。
また、lookup_object()直接呼び出すが処理する準備ができていないコードに潜在的なバグを引き起こすリスクもありますOBJ_NONE(このようなコードはすでにバグがありますが、使用lookup_unknown_object()頻度が低いため、隠れている可能性があります)。

ここでは2番目のオプションを選択しました。
リスクは高くないと思います(とにかくそのようなバグを見つけて修正したいと思います)。全体としてはより効率的であるはずです。

p5600の新しいテストは、改善を示しています(これはgit.gitにあります):

Test                                 HEAD^               HEAD
-------------------------------------------------------------------------------
5600.5: count commits                0.37(0.37+0.00)     0.38(0.38+0.00) +2.7%
5600.6: count non-promisor commits   11.74(11.37+0.37)   0.04(0.03+0.00) -99.7%

このスクリプトでは、新しく複製された部分リポジトリ内のすべてのオブジェクトがプロミサーオブジェクトであるため、特に大きな改善が見られます。
したがって、それらすべてにマークを付けた後、トラバースするものは何も残っていません。

于 2019-05-13T19:33:34.263 に答える
4

データの転送速度の上限がgitの「外部」で確立されているssh接続であることを認識した後、いくつかの実験を行ったところ、pcsp(Putty scp)の使用の上限は3.0 MB/sであることがわかりました。ブローフィッシュ暗号化スキームが適切に選択されたため。raw ftpを使用した制御実験では、転送速度が3.1 MB / sであることが示されたため、これがネットワークの上限であることが示されました。

これはvmwareハイパーバイザー内で実行され、ネットワークI / Oを実行するプロセスがほぼ100%CPUを使用しているため、ボトルネックがUbuntuネットワークカードドライバーであることが示されました。次に、vmwareツールがインストールされていても、何らかの理由で、カーネルがvmxnetドライバー(ハイパーバイザーと直接通信する)ではなく、vlanceドライバー(IRQおよびすべてを含む10 MBpsネットワークカードをエミュレート)を使用していることがわかりました。これで、サービスウィンドウが変更されるのを待ちます。

言い換えれば、問題はgitではなく、基盤となる「ハードウェア」にありました。

于 2011-11-21T10:35:51.543 に答える
2

私はgitcloneのベンチマークを行っています。

プロジェクトにサブモジュールが含まれている場合は、-jobsオプションを使用すると高速になります。例:

git clone --recursive --shallow-submodules --depth 1 --branch "your tag or branch" --jobs 5 --  "your remote repo"
于 2019-05-02T07:31:13.223 に答える
1

ログから、クローンはすでに完了しているようです。問題が、このプロセスを異なるマシンで複数回実行する必要がある場合は、リポジトリディレクトリをあるマシンから別のマシンにコピーするだけです。このようにして、各コピーとクローン元のリポジトリとの間の関係(リモート)が保持されます。

于 2011-11-18T10:06:20.007 に答える