共有ホストでgitリポジトリをホストしています。私のリポジトリには必然的にいくつかの非常に大きなファイルが含まれています。リポジトリで「gitgc」を実行しようとするたびに、メモリを使いすぎたために共有ホスティングプロバイダーによってプロセスが強制終了されます。git gcが消費できるメモリの量を制限する方法はありますか?私の望みは、メモリ使用量を速度と引き換えに、作業に少し時間がかかることです。
5 に答える
このリンクからの指示を使用しました。チャールズベイリーズが提案したのと同じ考え。
コマンドのコピーはここにあります:
git config --global pack.windowMemory "100m"
git config --global pack.packSizeLimit "100m"
git config --global pack.threads "1"
これは、共有ホスティングアカウントを持つhostgatorで私のために働きました。
はい、ヘルプページをgit config
見て、pack.*
オプション、具体的pack.depth
にpack.window
は、、、pack.windowMemory
を見てくださいpack.deltaCacheSize
。
gitは各オブジェクトをメモリにマップする必要があるため、完全に正確なサイズではありません。そのため、1つの非常に大きなオブジェクトは、ウィンドウとデルタキャッシュの設定に関係なく、多くのメモリ使用量を引き起こす可能性があります。
ローカルでパックし、パックファイルをリモート側に「手動で」転送し.keep
て、リモートgitがすべてを完全に再パックしようとしないようにファイルを追加する方がよい場合があります。
Gitrepackのメモリ使用量は次のとおり(pack.deltaCacheSize + pack.windowMemory) × pack.threads
です。それぞれのデフォルトは256MiB、無制限、nprocです。
デルタキャッシュは役に立ちません。ほとんどの時間はスライディングウィンドウでデルタを計算するために費やされ、その大部分は破棄されます。生存者をキャッシュして、一度(書き込み時に)再利用できるようにしても、実行時間は改善されません。そのキャッシュもスレッド間で共有されません。
デフォルトでは、ウィンドウメモリはpack.window
(gc.aggressiveWindow
)によって制限されます。ワーキングセットのサイズと効率は大きく異なるため、このようにパッキングを制限することはお勧めできません。pack.windowMemory
両方をはるかに高い値に上げ、ウィンドウサイズを制限することに依存するのが最善です。
最後に、スレッド化には、ワーキングセットを分割するという欠点があります。合計が同じになるようpack.threads
に増減pack.windowMemory
すると、実行時間が改善されます。
repackには他にも便利な調整機能(、、pack.depth
ビットpack.compression
マップオプション)がありますが、メモリの使用には影響しません。
デルタ属性をオフにして、これらのパス名のブロブのみのデルタ圧縮を無効にすることができます。
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
ます。
Git 2.18(2018年第2四半期)は、gcメモリの消費を改善します。
2.18より前では、 " "は作業中git pack-objects
に大量の""を割り当てる必要があります。サイズを縮小すると、パフォーマンスが大幅に向上します。
これはに影響します。struct object_entry
git gc
commit f6a5576、commit 3b13a5f、commit 0aca34e、commit ac77d0c、commit 27a7d06、commit 660b373 、 commit 0cb3c14 、 commit 898eba5、 commit 43fa44f、commit 06af3bb、commit b5c0cbd 、commit 0c6804a NguyễnTháiNgọcDuy()。(JunioCHamanoによってマージされました---コミットad635e8でpclouds
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.git
3.747Gから3.424Gに、または約320M削減し、8.5%減少しました。
再梱包の実行時間は、このシリーズ全体を通して同じままです。
アクセスできる(より大きい)大きなモノレポでのÆvarのテストではlinux-2.6.git
、7.9%の削減が示されているため、全体として期待される改善は約8%になるはずです。
Git 2.20(2018年第4四半期)では、1つのフォークに存在するオブジェクトが、同じフォークリポジトリに表示されない別のオブジェクトに対してデルタ化されていないことを確認するのが簡単になります。
Christian Couder( )によるcommit fe0ac2f、commit 108f530、commit f64ba53(2018年8月16日)を参照してください。
支援者:Jeff King()、およびDuy Nguyen()。ジェフキング()によるコミット9eb0986、コミット16d75fa、コミット28b8a73、コミットc8d521f(2018年8月16日)
を参照してください。
支援者:Jeff King()、およびDuy Nguyen()。(濱野純雄による合併---コミットf3504eachriscool
peff
pclouds
peff
peff
pclouds
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 edb673c、commit 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_slow
try_delta()
oe_get_size_slow
ll_find_deltas
読み取りミューテックスをに移動し、
packing_data
で初期化されるprepare_packing_dataで初期化することにより、これを解決しcmd_pack_objects
ます。
Git 2.21(2019年2月)は、git pack-objects
送信するオブジェクトのセットを計算する別のアルゴリズムを学習することで、パックのサイズを縮小する別の方法を見つけています。これは、結果のパックファイルをトレードオフして、トラバーサルコストを節約して小さなプッシュを優先します。
pack-objects
:pack.useSparse
設定を作成
''の'
--sparse
'フラグは、git pack-objects
オブジェクトの列挙に使用されるアルゴリズムを、作業ディレクトリの小さな円錐のみを変更する新しいオブジェクトをプッシュする個々のユーザーにとってより高速なアルゴリズムに変更します。
スパースアルゴリズムは、作業ディレクトリ全体に表示される新しいオブジェクトを送信する可能性が高いサーバーには推奨されません。
pack.useSparse
この新しいアルゴリズムを有効にする''設定を作成します。
これにより、' 'は、4つのレベルの 呼び出しに' 'フラグgit push
を渡すことなく、このアルゴリズムを使用できます。--sparse
run_command()
'
--no-sparse
'フラグが設定されている場合、この構成設定は上書きされます。
構成パックのドキュメントには、次のものが含まれています。
pack.useSparse:
trueの場合、Gitは、''オプションが存在する場合、デフォルト
--sparse
で''の''オプションを使用します。 このアルゴリズムは、新しいオブジェクトを導入するパスに表示されるツリーのみをウォークします。git pack-objects
--revs
これは、小さな変更を送信するパックを計算するときに、パフォーマンスに大きなメリットをもたらす可能性があります。
ただし、含まれているコミットに特定の種類の直接名前変更が含まれている場合は、パックファイルに追加のオブジェクトが追加される可能性があります。
具体的なイラストについては、「git push
巨大なレポには非常に遅い」を参照してください。
注:Git 2.24でコメントされているように、のような設定pack.useSparse
はまだ実験段階です。
Derrick Stolee()によるcommit aaf633c、 commit c6cc4c5、commit ad0fb65、commit 31b1de6、commit b068d9a、commit 7211b9e(2019年8月13日)を参照してください。( Junio C Hamanoによってマージされました---コミットf4f8dfe、2019年9月9日)derrickstolee
gitster
repo-settings
:feature.experimental
設定を作成
'
feature.experimental
'設定には、デフォルトになることを確約していない構成オプションが含まれていますが、追加のテストを使用できます。次の構成設定を更新して、新しいデフォルトを取得し、
repo_settings
まだ使用していない場合は構造体を使用します。
- 'pack.useSparse = true'
- 'fetch.negotiationAlgorithm = skipping'
Git 2.26(2020年第1四半期)ではgit pack-objects
、既存のパックに保存されているオブジェクトを再利用して結果を生成する方法が改善されました。
commit d2ea031、commit 92fb0db、commit bb514de、commit ff48302、commit e704fc7 、 commit 2f4af77、commit 8ebf529、commit 59b2829、commit 40d18ff、commit 14fbd26(18 Dec 2019)、commit 56d9cbe、commit 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 b017334、commit a9fd2f2、commit 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.experimental
Git 2.36(Q2 2022)で修正されました。
Elijah Newren()によるcommit 714edc6、commit a9a136c、commit 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.experimental
consecutive
git config
現在、そのマニュアルページに含まれています:
サーバーによって送信されるパックファイルの内容をネゴシエートするときに、ローカルリポジトリ内のコミットに関する情報がどのように送信されるかを制御します。
- ""に設定すると
consecutive
、連続するコミットをウォークオーバーして各コミットをチェックするアルゴリズムを使用します。- より速く収束するためにコミットをスキップするアルゴリズムを使用するには、 「」に設定し
skipping
ますが、必要以上にパックファイルが大きくなる可能性があります。または、「noop
」に設定すると、情報がまったく送信されなくなります。これにより、ほぼ確実に必要以上のパックファイルが作成されますが、ネゴシエーション手順はスキップされます。- 以前に行った設定を上書きし、デフォルトの動作を使用するには、「デフォルト」に設定します。
デフォルトは通常「
consecutive
」ですfeature.experimental
が、trueの場合、デフォルトは「skipping
」です。
値が不明な場合、'git fetch
'はエラーになります(unknown fetch negotiation algorithm
)。