1757048160
2025-09-05 00:55:00
FIL-Cはaを使用します 並列並列オンザフライグレースタックDijkstra正確な非移動 FUGC(FILの信じられないほどのゴミコレクター)と呼ばれるゴミコレクター。コレクター自体のソースコードを見つけることができます fugc.c、警告されていますが、そのコードは、ランタイムの残りの部分とコンパイラで多くのサポートロジックなしでは機能しない可能性があります。
FUGCの機能を分解しましょう:
-
並列:マーキングとスイープは、複数のスレッドで並行して発生します。コアが多いほど、コレクターの仕上げが速くなります。
-
同時:マーキングとスイープは、 デモ スレッド(つまり、プログラムのスレッド)。ミューテータースレッドは、停止してコレクターを待つ必要はありません。コレクタースレッドとミューテータースレッド間の相互作用は、ほとんど非ブロッキングです(ロックは、割り当ての遅いパスでのみ使用されます)。
-
オンザフライ:世界の停留所はありませんが、代わりに「ソフトハンドシェイク」(別名「ラグドサフェポイント」)を使用します。これは、GCがスレッドにいくつかの作業(スキャンスタックなど)を行うように依頼する可能性があることを意味しますが、スレッドは、コレクターや他のスレッドを待つことなく、自分の時間に非同期的にこれを行います。唯一の「一時停止」スレッドのエクスペリエンスは、ソフトハンドシェイクに応じて実行されるコールバックです。これは、そのスレッドのスタックの高さに囲まれて機能します。その「一時停止」は通常、あなたが典型的なものを通り抜けるかもしれない最も遅いパスよりも短いです
malloc実装。 -
Grey-Stack:コレクターは、FixPointにスレッドスタックを再実行する必要があると想定しています。つまり、GCは柔らかい握手から始まり、スタックをスキャンし、ループでマークします。このループが機能しなくなった場合、FUGCは別のソフトハンドシェイクを行います。それがより多くのオブジェクトを明らかにする場合、同時マーキングは履歴書を履きます。これにより、私たちが持つことができなくなります 負荷障壁 (ヒープからポインターをローカル変数にロードするときに計装は実行されません)。 aのみ 障壁を保存します 必要であり、その障壁は非常に単純です。この固定点は、GC中に新しく割り当てられたすべてのオブジェクトが事前にマークされているため、非常に迅速に収束します。
-
Dijkstra:FUGCがそのマーキングフェーズにある間に、ヒープまたはグローバル変数にあるオブジェクトにポインターフィールドを保存すると、新しく尖ったオブジェクトがマークされます。これはaと呼ばれます ディクストラバリア そして、それは一種です 障壁を保存します。灰色のスタックのために、のような負荷障壁はありません 古典的なダイクストラコレクター。 FUGCストアバリアは、最も遅いパスでリラックスしたメモリの順序で比較とスワップを使用します(GCが実行されていて、保存されているオブジェクトがまだマークされていない場合)。
-
正確:GCは正確に(正確に、別名、正確に)オブジェクトへのすべてのポインターを見つけますが、それ以上のものはありません。
llvm::FilPizlonatorランタイムは、根のポインターがスタック上の場所とグローバルのどこにあるかを常に把握していることを保証します。 FIL-Cランタイムには、ピズロン化コードと相互作用する低レベルコードでポインターを追跡するための巧妙なAPIおよびRubyコードジェネレーターがあります。すべてのオブジェクトは、彼らの発信ポインターがどこにあるかを知っています – 彼らは Invisicap 補助割り当て。 -
非移動:GCはオブジェクトを移動しません。これにより、並行性が簡単に実装でき、ミューテーターとコレクターの間の多くの同期を回避できます。ただし、FUGCはポインターを「移動」してオブジェクトを自由にします( 能力 無料のシングルトンへのポインタがあるので、解放された割り当てをマークする必要はありません)。
これにより、fugc anがなります 波面の進行 ゴミコレクター。波面の進行とは、ヒープを変更して、ミューテーターがコレクターの新しい作業を作成できないことを意味します。オブジェクトがマークされると、そのGCサイクルのマークはマークされたままになります。それもです 増分アップデート コレクター、GCの開始時にライブであったであろうオブジェクトは、収集サイクル中に自由になると解放される可能性があるためです。
fugcは依存しています SafePoints、それは次のとおりです。
-
Pollchecks コンパイラによって放出されます。
llvm::FilPizlonatorコンパイラパスは、Pollcheckが発生する前に、境界のある量の進行のみが可能になるほど十分に頻繁にポーリングを放出します。 Pollcheckの高速経路は、単なる負荷と収穫です。スローパスが実行されます Pollcheckコールバック、FUGCで機能します。 -
ソフトハンドシェイクは、すべてのスレッドでPollcheckコールバックを実行し、これが起こるのを待つように要求します。
-
入力/出口 機能。これは、Pollchecksを実行せずにSyscallsまたは長期にわたるランタイム関数でスレッドをブロックできるようにするためです。にあるスレッド 終了 州には、コレクター自体によって実行されるPollcheckコールバックがあります(ソフトハンドシェイクを行う場合)。 FIL-Cプログラムがブロックする唯一の方法は、入力中にループすること(ループごとに少なくとも1回、多くの場合、多くの場合、それ以上)を実行することを意味するか、ランタイムを呼び出してから終了することです。
セーフポイントは、スレッドをサポートするために不可欠です(FIL-CはPTHREADSを正常にサポートします)。たとえば、セーフポイントとは、ヒープからポインターをロードしてから使用することが安全であることを意味します。 GCは、次のPollcheckまたはExitまでそのメモリを削除することはできません。したがって、コンパイラとランタイムは、ロードされたときと次のPollcheck/Exitが発生するときの間のある時点で、ポインターがまだその時点でライブである場合にのみ、スタックスキャンのポインターが追跡されることを確認する必要があります。
セーフポイント機能もサポートしています 世界の停止、現在実装に使用されています
fork(2) そして、FUGCをデバッグするために(あなたが設定した場合 FUGC_STW 環境変数へ 1 その後、コレクターは世界を止めます。これはGCバグのトリアージに役立ちます。バグがSTWで再現する場合、それはストアの障壁の問題によるものではないことを意味します)。 SafePointインフラストラクチャは、安全な信号配信も可能にします。 FIL-Cは、実用的な方法で信号処理を使用することを可能にします。 SafePointingは、複数のスレッドと正確なごみ収集をサポートする仮想マシンの一般的な機能ですが、通常、すべてのスレッドから非同期アクティビティを要求するのではなく、世界を止めるためにのみ使用されます。見る ここ OpenJDKがそれをどのように行うかについての記事について。 FIL-Cの実装があります filc_runtime.c。
FUGCコレクターループの基本的なフローは次のとおりです。
- GCトリガーを待ちます。
- 店の壁をオンにし、次に、ノーオプコールバックでソフトな握手をします。
- ブラック割り当てをオンにします(新しいオブジェクトはマークされて割り当てられます)、次に、スレッドローカルキャッシュをリセットするコールバックでソフトハンドシェイクを使用します。
- グローバルルーツをマークします。
- スタックスキャンとスレッドローカルキャッシュの別のリセットを要求するコールバックを使用したソフトハンドシェイク。この後、すべてのコレクターマークスタックが空の場合は、ステップ7に進みます。
- トレース:マークスタック内の各オブジェクトについて、その発信参照(マークスタックが成長する可能性がある)をマークします。マークスタックが空になるまでこれを行います。次に、ステップ5に進みます。
- 店の壁をオフにして、スイープの準備をしてから、柔らかい握手をしてスレッドローカルキャッシュを再びリセットします。
- スイープを実行します。スイープ中に、オブジェクトは、たまたまスイークページから割り当てられている場合、またはalraedyに巻き込まれたページから割り当てられている場合は白に割り当てられます。
- 勝利!ステップ1に戻ります。
文献に精通している場合、FUGCはDLG(Doligez-Leroy-Gonthier)コレクターのようなものです( 二
論文 彼らは最初のバグに深刻なバグがあったため)、それはすべてを簡素化しますが、学問的に純粋ではない(FUGCの固定点ではなく、そうではない)を除いて、最初のバグに深刻なバグがあったため)。私は最初に作業中にグレイスタックのディクストラアプローチを思いつきました
フィジーワールドカップ‘s cmr and
分裂 ゴミコレクター。 DLGよりもFUGCの主な利点は、よりシンプルな(安価な)ストアバリアがあり、少し直感的なアルゴリズムであることです。 Fixpointは欠点のように思えますが、実際には数回の反復後に収束します。
さらに、FUGCはBitvector SIMDに基づいた掃引アルゴリズムに依存しています。これにより、マーキングと比較して、抜本的な速さが速くなります。これはおかげで作られています
Verse Heap Config
私が追加したこと
Libpas。 FUGCは通常費やします
ボーナス機能
FUGCは、Cスタイル、Javaスタイル、JavaScriptスタイルのメモリ管理のほとんどをサポートしています。それが何を意味するかを分解しましょう。
解放オブジェクト
あなたが電話するなら free、ランタイムはオブジェクトに無料としてフラグを立て、オブジェクトへの後続のアクセスはすべてトラップします。さらに、FUGCはオブジェクトからの発信参照をスキャンしません(それらにアクセスできなくなるため)。
また、FUGCはすべての機能ポインターをリダイレクトします(より低いs in Invisicaps Jargon)自由オブジェクトを使用して、代わりに無料のSingletonオブジェクトを指す。これにより、解放されたオブジェクトメモリを本当に再生することができます。
これは、自由化するオブジェクトを使用して防止できることを意味します GCによる漏れ。驚くべきことに、うまく機能するプログラム malloc/free (リークなし、クラッシュなし)GCに変換される(素朴な方法)(malloc GCから割り当てます free プログラムが決してアクセスしないぶら下がっているポインターのために、最終的には漏れている可能性があります。これらのダングリングポインターは、GCによってライブとして扱われます。 FUGCでは、それらのポインターを解放した場合、Fugcは本当にそれらを殺します。
ファイナライザー
FUGCは、を使用してファイナイザーキューをサポートします zgc_finq api in stdfil.h。この機能を使用すると、ファイナライザーをJavaのスタイルで実装できます。ただし、独自のファイナイザーキューをセットアップして、どのスレッドを処理するかを選択できます。
弱い参照
FUGCは、を使用して弱い参照をサポートしています zweak api in stdfil.h。弱い参照は、参照キューがないことを除いて、Javaの弱い参照と同じように機能します。 FIL-Cは、Phantomまたはソフト参照をサポートしていません。
弱いマップ
FUGCは、を使用して弱いマップをサポートします zweak_map api in stdfil.h。このAPIは、JavaScriptとほぼ同じように機能します WeakMap、FIL-Cの弱いマップを使用すると、すべての要素を反復し、要素のカウントを取得できます。
FUGCは、FIL-Cが誤用について可能な限り強力な保証を与えることを可能にします free:
-
オブジェクトを解放してからアクセスすると、トラップが発生することが保証されます。タグベースのアプローチとは異なり、メモリ開拓が強制されるまで無料で使用して使用します。 より低い 無料のシングルトンに任命する)。
-
オブジェクトを2回解放すると、トラップが発生することが保証されています。
-
オブジェクトを解放できないと、オブジェクトが回収されることを意味します。
#ワイヤC