41

共有ホストでgitリポジトリをホストしています。私のリポジトリには必然的にいくつかの非常に大きなファイルが含まれています。リポジトリで「gitgc」を実行しようとするたびに、メモリを使いすぎたために共有ホスティングプロバイダーによってプロセスが強制終了されます。git gcが消費できるメモリの量を制限する方法はありますか?私の望みは、メモリ使用量を速度と引き換えに、作業に少し時間がかかることです。

4

5 に答える 5

42

このリンクからの指示を使用しました。チャールズベイリーズが提案したのと同じ考え。

コマンドのコピーはここにあります:

git config --global pack.windowMemory "100m"
git config --global pack.packSizeLimit "100m"
git config --global pack.threads "1"

これは、共有ホスティングアカウントを持つhostgatorで私のために働きました。

于 2012-01-06T16:59:42.417 に答える
16

はい、ヘルプページをgit config見て、pack.*オプション、具体的pack.depthpack.windowは、、、pack.windowMemoryを見てくださいpack.deltaCacheSize

gitは各オブジェクトをメモリにマップする必要があるため、完全に正確なサイズではありません。そのため、1つの非常に大きなオブジェクトは、ウィンドウとデルタキャッシュの設定に関係なく、多くのメモリ使用量を引き起こす可能性があります。

ローカルでパックし、パックファイルをリモート側に「手動で」転送し.keepて、リモートgitがすべてを完全に再パックしようとしないようにファイルを追加する方がよい場合があります。

于 2010-06-22T18:05:04.700 に答える
15

Gitrepackのメモリ使用量は次のとおり(pack.deltaCacheSize + pack.windowMemory) × pack.threadsです。それぞれのデフォルトは256MiB、無制限、nprocです。

デルタキャッシュは役に立ちません。ほとんどの時間はスライディングウィンドウでデルタを計算するために費やされ、その大部分は破棄されます。生存者をキャッシュして、一度(書き込み時に)再利用できるようにしても、実行時間は改善されません。そのキャッシュもスレッド間で共有されません。

デフォルトでは、ウィンドウメモリはpack.windowgc.aggressiveWindow)によって制限されます。ワーキングセットのサイズと効率は大きく異なるため、このようにパッキングを制限することはお勧めできません。pack.windowMemory両方をはるかに高い値に上げ、ウィンドウサイズを制限することに依存するのが最善です。

最後に、スレッド化には、ワーキングセットを分割するという欠点があります。合計が同じになるようpack.threadsに増減pack.windowMemoryすると、実行時間が改善されます。

repackには他にも便利な調整機能(、、pack.depthビットpack.compressionマップオプション)がありますが、メモリの使用には影響しません。

于 2015-01-08T11:50:30.137 に答える
7

デルタ属性をオフにして、これらのパス名のブロブのみのデルタ圧縮を無効にすることができます。

In foo/.git/info/attributes(またはfoo.git/info/attributesベアリポジトリの場合)(gitattributesのdeltaエントリを参照し、パターン構文についてはgitignoreを参照してください):

/large_file_dir/* -delta
*.psd -delta
/data/*.iso -delta
/some/big/file -delta
another/file/that/is/large -delta

これは、リポジトリのクローンには影響しません。他のリポジトリ(つまりクローン)に影響を与えるには、.gitattributesファイルの代わりに(またはファイルに加えて)属性をファイルに入れinfo/attributesます。

于 2010-06-22T20:00:05.143 に答える
3

Git 2.18(2018年第2四半期)は、gcメモリの消費を改善します。
2.18より前では、 " "は作業中git pack-objectsに大量の""を割り当てる必要があります。サイズを縮小すると、パフォーマンスが大幅に向上します。 これはに影響します。struct object_entry
git gc

commit f6a5576、commit 3b13a5fcommit 0aca34ecommit ac77d0c、commit 27a7d06、commit 660b373 commit 0cb3c14 commit 898eba5、 commit 43fa44fcommit 06af3bbcommit b5c0cbd 、commit 0c6804a NguyễnTháiNgọcDuy(JunioCHamanoによってマージされました---コミットad635e8pclouds
gitster、2018年5月23日)

pack-objects:メンバーを並べ替えて縮小するstruct object_entry

以前のパッチでは、この構造体に多くの穴とパディングが残っています。
このパッチは、メンバーを並べ替えて、構造体を80バイト(64ビットシステムの136バイトから、フィールドの縮小が行われる前)に縮小し、16ビットを残します(実際にビットが不足した場合は、in_pack_header_sizeにさらに2つ) 。

これは、一連のメモリ削減パッチの最後です(最初のパッチについては、「pack-objects:struct object_entryに関するドキュメント」を参照してください)。

全体として、再梱包メモリのサイズをlinux-2.6.git3.747Gから3.424Gに、または約320M削減し、8.5%減少しました。
再梱包の実行時間は、このシリーズ全体を通して同じままです。
アクセスできる(より大きい)大きなモノレポでのÆvarのテストではlinux-2.6.git、7.9%の削減が示されているため、全体として期待される改善は約8%になるはずです。


Git 2.20(2018年第4四半期)では、1つのフォークに存在するオブジェクトが、同じフォークリポジトリに表示されない別のオブジェクトに対してデルタ化されていないことを確認するのが簡単になります。

Christian Couder( )によるcommit fe0ac2fcommit 108f530commit f64ba53(2018年8月16日)を参照してください。 支援者:Jeff King(、およびDuy Nguyen(ジェフキング()によるコミット9eb0986コミット16d75faコミット28b8a73コミットc8d521f(2018年8月16日) を参照してください。 支援者:Jeff King(、およびDuy Nguyen(濱野純雄による合併---コミットf3504eachriscool
peffpclouds
peff
peffpclouds
gitster、2018年9月17日)

pack-objects:' layer'を''にstruct packing_data移動

これにより、「struct object_entry」のサイズが88バイトから80バイトに減少し、オブジェクトのパッキングがより効率的になります。

たとえば、12MオブジェクトのLinuxリポジトリでgit pack-objects --allは、レイヤー機能が使用されていない場合でも、追加の96MBメモリが必要です。


Git 2.21(2019年2月)では、小さなバグgit pack-objectsが修正されていることに注意してください。

Patrick Hogg( ``)によるcommit edb673ccommit 459307b(2019年1月25日)を参照してください。 支援者:濱野純雄(( Junio C Hamanoによってマージされました---コミットd243a32、2019年2月5日
gitster
gitster

pack-objects:読み取りミューテックスをpacking_data構造体に移動

ac77d0c( " pack-objects:structの縮小サイズフィールド"、2018-04-14)は、への並列呼び出しでスレッドセーフのため object_entryに新しく導入されたread_lock/read_unlockの追加の使用法を追加しました。 残念ながら、シリアルコードでも使用されており、その一部は。の最初の呼び出しの前に呼び出されます 。 そのため、読み取りミューテックスは初期化されることが保証されていません。oe_get_size_slowtry_delta()
oe_get_size_slowll_find_deltas

読み取りミューテックスをに移動し、packing_dataで初期化されるprepare_packing_dataで初期化することにより、これを解決しcmd_pack_objectsます。


Git 2.21(2019年2月)は、git pack-objects送信するオブジェクトのセットを計算する別のアルゴリズムを学習することで、パックのサイズを縮小する別の方法を見つけています。これは、結果のパックファイルをトレードオフして、トラバーサルコストを節約して小さなプッシュを優先します。

pack-objectspack.useSparse設定を作成

''の' --sparse'フラグは、git pack-objectsオブジェクトの列挙に使用されるアルゴリズムを、作業ディレクトリの小さな円錐のみを変更する新しいオブジェクトをプッシュする個々のユーザーにとってより高速なアルゴリズムに変更します。
スパースアルゴリズムは、作業ディレクトリ全体に表示される新しいオブジェクトを送信する可能性が高いサーバーには推奨されません。

pack.useSparseこの新しいアルゴリズムを有効にする''設定を作成します。
これにより、' 'は、4つのレベルの 呼び出しに' 'フラグgit pushを渡すことなく、このアルゴリズムを使用できます。--sparserun_command()

' --no-sparse'フラグが設定されている場合、この構成設定は上書きされます。

構成パックのドキュメントには、次のものが含まれています。

pack.useSparse:

trueの場合、Gitは、''オプションが存在する場合、デフォルト--sparseで''の''オプションを使用します。 このアルゴリズムは、新しいオブジェクトを導入するパスに表示されるツリーのみをウォークします。git pack-objects--revs

これは、小さな変更を送信するパックを計算するときに、パフォーマンスに大きなメリットをもたらす可能性があります。

ただし、含まれているコミットに特定の種類の直接名前変更が含まれている場合は、パックファイルに追加のオブジェクトが追加される可能性があります。

具体的なイラストについては、「git push巨大なレポには非常に遅い」を参照してください。


注:Git 2.24でコメントされているように、のような設定pack.useSparseはまだ実験段階です。

Derrick Stolee(によるcommit aaf633c、 commit c6cc4c5commit ad0fb65commit 31b1de6commit b068d9acommit 7211b9e(2019年8月13日)を参照してください。( Junio C Hamanoによってマージされました---コミットf4f8dfe、2019年9月9日derrickstolee
gitster

repo-settingsfeature.experimental設定を作成

' feature.experimental'設定には、デフォルトになることを確約していない構成オプションが含まれていますが、追加のテストを使用できます

次の構成設定を更新して、新しいデフォルトを取得し、repo_settingsまだ使用していない場合は構造体を使用します。

  • 'pack.useSparse = true'
  • 'fetch.negotiationAlgorithm = skipping'

Git 2.26(2020年第1四半期)ではgit pack-objects、既存のパックに保存されているオブジェクトを再利用して結果を生成する方法が改善されました。

commit d2ea031、commit 92fb0dbcommit bb514decommit ff48302commit e704fc7 commit 2f4af77commit 8ebf529commit 59b2829commit 40d18ffcommit 14fbd26(18 Dec 2019)、commit 56d9cbecommit bab28d9(13 Sep 2019)を参照してください。 peff
濱野純雄によって合併gitster---コミットa14aebe、2020年2月14日

pack-objects:部分的なパックファイルの再利用を改善する

支援者:ジョナサン・タン
サインオフ:ジェフ・キング
サインオフ:クリスチャン・クーダー

既存のパックファイルからのデルタを再利用する古いコードは、パックのセグメント全体を逐語的にダンプしようとしました。これは、実際にオブジェクトをパッキングリストに追加する従来の方法よりも高速ですが、あまり頻繁には実行されませんでした。この新しいコードは、実際には中立的な立場にあります。オブジェクトごとの作業を行いますが、従来よりもはるかに少なくなります

新しいコードの一般的な戦略は、含めるパックファイルからオブジェクトのビットマップを作成し、それを繰り返し処理して、各オブジェクトをディスク上のパックとまったく同じように書き出すことですが、パックリストには追加しません。 (これはメモリを消費し、デルタの検索スペースを増やします)。

複雑な点の1つは、一部のオブジェクトを省略している場合、送信していないベースに対してデルタを設定できないことです。したがって、各オブジェクトをチェックインしtry_partial_reuse()て、デルタがあることを確認する必要があります。

パフォーマンスに関しては、最悪の場合、送信するオブジェクトと送信しないオブジェクトがインターリーブされ、オブジェクトと同じ数のチャンクが存在する可能性があります。しかし実際には、大きなチャンクを送信します。

たとえば、GitHubサーバーにtorvalds / linuxをパックすると、650万個のオブジェクトが再利用されますが、必要なチャンクは5万個までです。


Git 2.34(Q4 2021)では、git repackそれ自体(によって使用されるgit gc)がメモリ使用量の削減の恩恵を受けています。

Taylor Blau()によるcommit b017334commit a9fd2f2commit a241878(2021年8月29日)を参照してください。( Junio C Hamanoによってマージされました---コミット9559de3、2021年9月10日ttaylorr
gitster

builtin/pack-objects.c:重複するハッシュルックアップを削除する

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

08cdfb1の元のコード( "pack-objects --keep-unreachable"、2007-09-16、Git v1.5.4-rc0 --merge では、各オブジェクトをタイプ `` obj-> type wherefrom.でパッキングリストに追加,objますlookup_unknown_object()
オブジェクトを既に検索して解析していない限り、これはになりますOBJ_NONE。ビットを「0」に設定し、後で実際のタイプを決定するので、これで
問題ありません。oe_set_type()type_valid

したがって、オブジェクトルックアップから必要なのはflagsフィールドへのアクセスだけです。これにより、オブジェクトを追加したことをマークして、再度追加しないようにすることができます(オブジェクトからオブジェクトを取得する代わりに直接OBJECT_ADDED渡すことができます)。OBJ_NONE

しかし、add_object_entry()すでに重複を拒否しています!これは7a979d9(「シンパック-デルタベースが欠落しているパックファイルを作成する」、2006-02-19、Git v1.3.0- rc1-マージ)以降の動作ですが、08cdfb1はこれを利用しませんでした。
さらに、OBJECT_ADDEDチェックを行うには、でハッシュルックアップを実行する必要がありますobj_hash

したがって、ここで触れている場所がそれをチェックする唯一の場所であるため、呼び出しを完全にドロップでき、フラグlookup_unknown_object()ドロップできます。OBJECT_ADDED

最終的に、同じ数のハッシュルックアップを実行しますが、オブジェクトの割り当てにメモリを浪費しないという追加のボーナスがありOBJ_NONEます(トラバースしている場合は、最終的に必要になりますが、このコードパスの要点は次のとおりです。トラバースしないでください)。


fetch.negotiationAlgorithmと構成変数間の相互作用は、 feature.experimentalGit 2.36(Q2 2022)で修正されました。

Elijah Newren()によるcommit 714edc6commit a9a136ccommit a68c5b9(2022年2月2日)を参照してください。( Junio C Hamanoによってマージされました---コミット70ff41f、2022年2月16日newren
gitster

repo-settings:従来のデフォルトの名前を変更fetch.negotiationAlgorithm

サインオフ-作成者:Elijah Newren

従来のデフォルトfetch.negotiationAlgorithmに''という名前を付けますconsecutive
また、' default'を選択して、Gitに選択肢を決定させることもできます(現在、trueskippingの場合は''を選択し、そうでない場合は''を選択します)。 それに応じてドキュメントを更新してください。feature.experimentalconsecutive

git config現在、そのマニュアルページに含まれています:

サーバーによって送信されるパックファイルの内容をネゴシエートするときに、ローカルリポジトリ内のコミットに関する情報がどのように送信されるかを制御します。

  • ""に設定するとconsecutive、連続するコミットをウォークオーバーして各コミットをチェックするアルゴリズムを使用します。
  • より速く収束するためにコミットをスキップするアルゴリズムを使用するには、 「」に設定しskippingますが、必要以上にパックファイルが大きくなる可能性があります。または、「noop」に設定すると、情報がまったく送信されなくなります。これにより、ほぼ確実に必要以上のパックファイルが作成されますが、ネゴシエーション手順はスキップされます。
  • 以前に行った設定を上書きし、デフォルトの動作を使用するには、「デフォルト」に設定します。

デフォルトは通常「consecutive」ですfeature.experimentalが、trueの場合、デフォルトは「skipping」です。
値が不明な場合、' git fetch'はエラーになります(unknown fetch negotiation algorithm)。

于 2018-05-25T23:11:03.820 に答える