みなさんこんにちは。 Phantomを続行します。 理解するには、
永続RAM に関する記事と、オープンシステム上のPhantomに関する一般的な記事を読むと便利です。 しかし、できます。
したがって、アプリケーションプログラムに永続的なランダムアクセスメモリを提供し、一般に永続的な「ライフ」を提供するOS(または単に環境、それは問題ではありません)があります。 プログラムは、管理された(管理された)ポインター、オブジェクトバイトコードマシンを備えた共通のアドレス空間に存在し、OSの再起動に気付かず、一般に満足しています。
明らかに、そのような環境ではガベージコレクションが必要です。 でも何?
いくつかの特定の問題があります。
まず、理論的には、このような環境での仮想メモリの量は膨大です-テラバイト、ディスクのコンテンツ全体。 結局のところ、すべてを常にメモリに表示します。
第二に、私たちは世界のアルゴリズムを止めるのが嫌いです。 通常のプロセスで30秒間の停止が許容される場合、仮想メモリでは、ほとんどの場合、ディスク上で、すでに30分または30分ではありません!
最後に、完全なガベージコレクションが半日であると仮定した場合、おそらく満足できません。完全に正直ではありませんが、何らかの迅速なガベージコレクションプロセスを用意しておくといいでしょう。 90%はすでに良好です。
ここで予約が必要です。 一般的に、数テラバイトの仮想メモリがあるシステムでは、これはそれほど重要ではありません-半日メモリを解放しなくてもそれほど多くないかもしれません-たとえば、2、3、5ギガバイトが消費されます50ギガバイト-残念なことではなく、ディスクは大きいです。
しかし、ほとんどの場合、これはメモリの大きな断片化につながります-多くのローカル変数は多くの遠くのページに散らばりますが、最新の情報が散在する小さなものには大量の無関係なガベージが散在し、RAMの負荷が大幅に増加する可能性が高いです。
OK、合計2つのタスクがあります。
- 高速で、安価で、場合によっては不完全(すべてのガベージを収集しない)、連続使用のためのノンストップアルゴリズム。 彼が「タッチ」するメモリはメモリ内で実在し、ディスクに排出されないものと想定されています。
- 完全で、おそらく長くて高価ですが、アドレス空間全体のノンストップ(!)アルゴリズム。 「メモリ」にアクセスすると、99%の確率でディスクに格納されると想定されています。
2番目の要件は非現実的であるように見えますが、実際にはそうです。 完全なメモリアセンブリは、ほとんどすべてのオブジェクト(一部のアルゴリズムの一部を最適化できる)のバイパスであり、それらがディスクおよびテラバイトディスク上にある場合、推定時間は1日ではないにしても数時間です。 ノンストップとは何ですか?
興味深い考えがレスキューに出てきます。これは、よくあることですが、誰かに読んだらすぐに明らかになります。昨日ゴミだったオブジェクトは、明日ゴミになります。
これは、実際には、昨日のシステムのメモリ全体の写真があれば、その写真からガベージコレクションを正確に行うことができるということです。 さらに、そこにあるゴミは、現在のバージョンのメモリでも解放できます!
しかし、永続的なランダムアクセスメモリを備えたOSは、メモリ状態の完全な「写真」を作成するために必要なものです。
(
このような概念的な偶然の一致が生じたとき、私は本当に大好きだと言わなければなりません。私にとっては、システムのモデルが非常に全体的で直交しているという兆候です。 )
したがって、驚くべき状況が発生します。システムのメモリの「写真」があり、最も一般的なマークアンドスイープアルゴリズムを使用しても、それを使用してゴミを収集できます。
簡単に言えば、どのように配置されているかを思い出させてください。すべての到達可能なオブジェクトへのリンクをたどって、「ゴミではない」というマーカーを付けます。 それから、私たちはすべてをあちこち調べますが、マーカーのないものはゴミです。
ただし、ここでは最適化の問題が多数発生します。
明らかなことから始めましょう。ディスクへの書き込みは高価で危険です。障害が発生した場合、システムのスナップショットが失われ、これは受け入れられません。
したがって、最適化が必要です。 2つの選択肢があります。
1つは、ガベージコレクションプロセスでスナップショットのコピーを個別に作成することです。 ひどく高価-ディスクメモリの量をほぼ2倍にする必要があります。 そして、ほぼすべてのページを上書きします。
2番目は、元の(常に良い)に触れることではなく、マーカーを別の並列(オブジェクトアドレスで並べ替えられた?)バッファーに、おそらくハッシュマップまたは並べ替えられたツリーの形式で配置することです。
オフハンド、選択は明らかです。 しかし、おそらく3番目のオプションがありますか?
それ自体を示唆する別のポイントは、世代のラベル付けです。 直感的には、データの90%が条件付きでゴミになることは決してないようです(クラスコード、音楽やビデオを含むオブジェクト)。これらはすべて何世紀も保存されており、明らかに毎日の検証は不要です。
おそらく、大規模なアセンブリも部分的に作成されることがあります。たとえば、最後の世代のみが1日に1回、最後の2回が2日ごとに2回処理され、週末にすべてが揺らぐ場合があります。 一般的なクリーニング。
ただし、メインアロケーターと高速ヒントヒントコレクターに問い合わせることができます。 たとえば、最下位の条件付き「定数」世代(クラスと巨大な定数オブジェクトが配置されている)の作業オブジェクトのプロセスで変更された場合、これが完全なアセンブリのトリガーになります。
実際、今日のPhantom OSでは、リファレンスカウンターに基づいて高速アルゴリズムのみが実装されています。 完全なコレクターは彼のヒーローを待っています。
ちなみに、高速では、すべてが簡単ではありません。 そこには解決できないものがあります(心配する必要はありませんが、ほとんど解決しました:)レースの問題は、オブジェクトの使用回数の増分の同期です。
その本質はシンプルです。 オブジェクトAのフィールドからオブジェクトBへのリンクを読み取っています。現在、所有(使用)している(リンク)ため、オブジェクトB内の参照カウンターを1増やします。
object *b_ptr = a[xx]; b_ptr->ref_count++;
しかし-ここに問題があります-この行のペアと別のスレッドの間でコンテキスト切り替えが発生し、その瞬間にオブジェクトAからBへのこのまさにリンクが取られ、消去されました。そしてそれは最後のものでした。 そして、参照カウンターがゼロになり、オブジェクトが削除されました。 そして、それへのリンクのカウンターを増やし始めました。 そして、彼はすでに殺され、片付けられ、他の誰かに割り当てられ、完全に異なるデータを含んでいます。
楽しいですか? そして、オブジェクトフィールドの読み取りごとにミューテックスを設定することはありません。その場合、マシンはそのようなミューテックスから抜け出すことはなく、ロックとロック解除のみを行います。 スピンロックでさえ、コードの複数回の、何倍もの減速につながります。
受け入れられない。
ソリューションは次のようになります。すべての仮想マシンのすべてのスレッドが仮想マシン命令の境界を通過した後にのみ、オブジェクトを実際に破棄します。 これにより、すべてのデクリメントとインクリメントが終了します。 これにはメカニズムがあり、すでにスナップショットに使用されています。
オブジェクトの最適化(最適化でもあります)のタスクには触れなかったことに留意して、今日はここで終わります。 また、一般的に言えば、終わりはありません。 それとは別に、割り当ての高度なローカリゼーションと、スレッドによる高速オブジェクトの領域の分割を伴うオブジェクトアロケータを記述するタスクがあります。 また、アロケータの入り口での混雑がないように、アロケータミューテックスのアリーナへの間隔もあります。
実際、これらはすべてPhantom OSプロジェクトで発生するタスクの非常に良い例です。非現実的なものはありませんが、一見必要な問題を回避するために、優れたエンジニアリングソリューションが常に必要です。