ホームページ > バックエンド開発 > C#.Net チュートリアル > .Netガベージコレクションの仕組み原理(2)

.Netガベージコレクションの仕組み原理(2)

黄舟
リリース: 2017-02-17 11:20:18
オリジナル
1393 人が閲覧しました

英語原文: Jeffrey Richter

編集者: Zhao Yukai

リンク http://www.php.cn/


前回の記事では、.Net ガベージ コレクションの基本原理と、.Net ガベージ コレクションの実装について紹介しました。ガベージ コレクションの最終的な方法 内部メカニズム。この記事では、弱参照オブジェクト、世代、マルチスレッド ガベージ コレクション、ラージ オブジェクト処理、およびガベージ コレクションに関連するパフォーマンス カウンターについて説明します。
弱参照オブジェクトから始めましょう。弱参照オブジェクトは、大きなオブジェクトによって引き起こされるメモリ負荷を軽減できます。
弱参照
プログラムのルート オブジェクトがオブジェクトを指している場合、そのオブジェクトは到達可能ですが、ガベージ コレクターはそれをリサイクルできません。これは、オブジェクトへの強参照と呼ばれます。強参照の反対は弱参照です。オブジェクトに弱参照がある場合、ガベージ コレクターはオブジェクトを再利用できますが、プログラムがオブジェクトにアクセスすることもできます。どうしたの?以下をお読みください。

オブジェクトに弱い参照しかなく、ガベージ コレクターが実行されている場合、そのオブジェクトがプログラムの後半でアクセスされると、アクセスは失敗します。一方、弱参照オブジェクトを使用するには、ガベージ コレクターがオブジェクトを収集する前にプログラムがオブジェクトへの強参照を作成する必要があります (強参照を取得した後)。ガベージ コレクターは、このオブジェクトをリサイクルできません。これは少し複雑なので、コードで説明しましょう:

void Method() {
//创建对象的强引用
Object o = new Object(); 
// 用一个短弱引用对象弱引用o.
WeakReference wr = new WeakReference(o);

o = null; // 移除对象的强引用

o = wr.Target; //尝试从弱引用对象中获得对象的强引用
if (o == null) {
// 如果对象为空说明对象已经被垃圾回收器回收掉了
} else {
// 如果垃圾回收器还没有回收此对象就可以继续使用对象了
}
}
ログイン後にコピー

なぜ弱いオブジェクトが必要なのでしょうか?一部のデータは作成が簡単ですが、大量のメモリを必要とするためです。たとえば、ユーザーのハードディスク上のすべてのフォルダーとファイル名にアクセスする必要があるプログラムがある場合、プログラムが初めてこのデータを必要とするときに、ユーザーのディスクにアクセスしてデータを生成できます。毎回ディスクを読み取ってデータを取得するのではなく、データを使用してメモリ内のデータにアクセスできるため、プログラムのパフォーマンスが向上します。

问题是这个数据可能相当大,需要相当大的内存。如果用户去操作程序的另外一部分功能了,这块相当大的内存就没有占用的必要了。你可以通过代码删除这些数据,但是如果用户马上切换到需要这块数据的功能上,你就必须重新从用户的磁盘上构建这个数据。弱引用为这种场景提供了一种简单有效的方案。
当用户切换到其他功能时,你可以为这个数据创建一个弱引用对象,并把对这个数据的强引用解除掉。这样如果程序占用的内存很低,垃圾回收操作就不会触发,弱引用对象就不会被回收掉;这样当程序需要使用这块数据时就可以通过一个强引用来获得数据,如果成功得到了对象引用,程序就没有必要再次读取用户的磁盘了。

WeakReference类型提供了两个构造函数:


WeakReference(object target);
WeakReference(object target, bool trackResurrection);
ログイン後にコピー

target参数显然就是弱引用要跟踪的对象了。trackResurrection参数表示当对象的Finalize方法执行之后是否还要跟踪这个对象。默认这个参数是false。有关对象的复活请参考这里。

便宜上、復活オブジェクトを追跡しない弱い参照を「短い弱参照」と呼び、復活オブジェクトを追跡したい弱い参照を「長い弱参照」と呼びます。オブジェクトが Finalize メソッドを実装していない場合、長い弱参照と短い弱い参照はまったく同じになります。長い弱参照の使用を避けることを強くお勧めします。長い弱参照を使用すると、動作が予測できない可能性がある復活したオブジェクトを使用できます。 WeakReference を使用してオブジェクトを参照した後は、このオブジェクトのすべての強参照を null に設定することをお勧めします。強参照が存在する場合、ガベージ コレクターは弱参照が指すオブジェクトを再利用できなくなります。
ターゲット オブジェクトへの弱い参照を使用する場合は、ターゲット オブジェクトの強い参照を作成する必要があります。これは非常に簡単です。 object a = WeekRefer.Target; を使用して、 a が空か弱いかを判断する必要があります。空の場合のみ、引き続き使用できます。空の場合、オブジェクトはガベージ コレクターによってリサイクルされており、他のメソッドを通じてオブジェクトを再取得する必要があることを意味します。

弱参照の内部実装 前の説明から、弱参照オブジェクトは一般のオブジェクトとは明らかに異なる方法で処理されることが推測できます。一般に、オブジェクトが別のオブジェクトを参照している場合、それは強参照であるため、ガベージ コレクターは参照先のオブジェクトをリサイクルできません。ただし、WeakReference オブジェクトの場合はこの限りではありません。
弱いオブジェクトがどのように機能するかを完全に理解するには、マネージド ヒープも確認する必要があります。マネージド ヒープには 2 つの内部データ構造があり、それらの唯一の役割は弱参照を管理することです。これらを長い弱参照テーブルと呼ぶことができ、これら 2 つのテーブルはマネージド ヒープに弱参照ターゲット オブジェクト ポインターを格納します。
プログラムの実行開始時は、両方のテーブルが空です。 WeakReference オブジェクトを作成すると、オブジェクトはマネージド ヒープに割り当てられませんが、弱いオブジェクト テーブルに空のスロット (Empty Slot) が作成されます。短い弱参照オブジェクトは短い弱参照オブジェクト テーブルに配置され、長い弱参照オブジェクトは長い弱参照テーブルに配置されます。
空のスロットが見つかると、空のスロットの値が弱参照ターゲット オブジェクトのアドレスに設定されます。明らかに、長い弱オブジェクト テーブルと短い弱オブジェクト テーブル内のオブジェクトは、アプリケーションのルート オブジェクトとは見なされません。ガベージ コレクターは、長い弱いオブジェクト テーブルと短い弱いオブジェクト テーブルのデータを収集しません。
ガベージ コレクションが実行されると何が起こるかを見てみましょう:
1. ガベージ コレクターは、到達可能なオブジェクト グラフを構築します。
2. ガベージ コレクターは、弱いオブジェクトの場合にスキャンします。テーブルは、ポイントされたオブジェクトが到達可能なオブジェクト グラフ内にない場合、そのオブジェクトはガベージ オブジェクトとしてマークされ、ショート オブジェクト テーブル内のオブジェクト ポインタは null に設定されます
3。ガベージ コレクターはファイナライズ キューをスキャンします。上記)、キュー内のオブジェクトが到達可能なオブジェクト グラフにない場合、オブジェクトはファイナライゼーション キューから Feachable キューに移動され、この時点でオブジェクトは到達可能なオブジェクトとしてマークされ、ガベージではなくなります。ガベージ コレクターは、長くて弱い参照テーブルをスキャンします。テーブル内のオブジェクトが到達可能オブジェクト グラフにない場合 (到達可能オブジェクト グラフには Feachable キュー内のオブジェクトが含まれます)、長い参照オブジェクト テーブル内の対応するオブジェクト ポインターを null に設定します
5 ガベージ コレクターは到達可能オブジェクトを移動します
。一度ガベージ コレクターの動作プロセスを理解すると、弱参照がどのように機能するかを理解するのは簡単です。 WeakReference の Target プロパティにアクセスすると、システムは弱いオブジェクト テーブル内のターゲット オブジェクト ポインターを返します。それが null の場合、オブジェクトがリサイクルされたことを意味します。
短い弱参照は復活を追跡しません。つまり、ガベージ コレクターは、ファイナライゼーション キューをスキャンする前に、弱参照テーブルで指されているオブジェクトがガベージ オブジェクトかどうかを確認できます。
長い弱参照は、復活したオブジェクトを追跡します。つまり、ガベージ コレクターは、オブジェクトがリサイクルされたことを確認した後、弱参照テーブル内のポインターを null に設定する必要があります。

世代:
.Net ガベージ コレクションに関して、C++ または C プログラマは、この方法でメモリを管理するとパフォーマンス上の問題が発生するのではないかと疑問に思うかもしれません。 GC 開発者は、パフォーマンスを向上させるためにガベージ コレクターを常に調整しています。生成は、ガベージ コレクションがパフォーマンスに与える影響を軽減するメカニズムです。ガベージ コレクターは、次のステートメントが当てはまると想定します。 1. オブジェクトが新しいほど、オブジェクトのライフ サイクルは短くなります。 2. オブジェクトが古いほど、オブジェクトのライフ サイクルは長くなります。 3. 通常、新しいオブジェクトは相互に参照関係を持つ可能性が高くなります
4. ヒープ全体を圧縮するよりも、ヒープの一部を圧縮する方が高速です
もちろん、上記の仮定が当てはまることは、多数の研究で証明されています。たくさんのプログラム。それでは、これらの仮定がガベージ コレクターの動作にどのような影響を与えるかについて話しましょう。
プログラムの初期化時には、マネージド ヒープ上にオブジェクトはありません。このとき、マネージド ヒープに新たに追加されるオブジェクトは世代 0 です。次の図に示すように、世代 0 のオブジェクトは最も若いオブジェクトであり、ガベージ コレクターによってチェックされたことがありません。



図 1 マネージド ヒープ上のジェネレーション 0 オブジェクト

さらにオブジェクトがヒープに追加されると、ヒープがいっぱいになるとガベージ コレクションがトリガーされます。ガベージ コレクターはマネージド ヒープを分析するときに、ガベージ オブジェクト (図 2 の薄紫色のブロック) と非ガベージ オブジェクトのグラフを構築します。リサイクルされていないすべてのオブジェクトは、ヒープの一番下に移動され、圧縮されます。リサイクルされていないこれらのオブジェクトは、図 2 に示すように、ジェネレーション 1 オブジェクトになります



図 2 マネージド ヒープ上のジェネレーション 0 および 1 オブジェクト

さらに多くのオブジェクトがヒープに割り当てられると、新しいオブジェクトは世代 0 領域に配置されます。ジェネレーション 0 ヒープがいっぱいになると、ガベージ コレクションがトリガーされます。このとき、生き残ったオブジェクトは世代 1 のオブジェクトとなり、ヒープの最下位に移動されます。ガベージ コレクションが発生した後、世代 1 のオブジェクトに残ったオブジェクトは世代 2 のオブジェクトに昇格され、移動および圧縮されます。図 3 に示すように:



図 3 マネージド ヒープ上の生成 0、1、および 2 オブジェクト

2代对象是目前垃圾回收器的最高代,当再次垃圾回收时,没有回收的对象的代数依然保持2.
垃圾回收分代为什么可以优化性能
如前所述,分代回收可以提高性能。当堆填满之后会触发垃圾回收,垃圾回收器可以只选择0代上的对象进行回收,而忽略更高代堆上的对象。然而,由于越年轻的对象生命周期越短,因此,回收0代堆可以回收相当多的内存,而且回收所耗的性能也比回收所有代对象要少得多。
这是分代垃圾回收的最简单优化。分代回收不需要便利整个托管堆,如果一个根对象引用了一个高代对象,那么垃圾回收器可以忽略高代对象和其引用对象的遍历,这会大大减少构建可达对象图的时间。
如果回收0代对象没有释放出足够的内存,垃圾回收器会尝试回收1代和0代堆;如果仍然没有获得足够的内存,那么垃圾回收器会尝试回收2,1,0代堆。具体会回收那一代对象的算法不是确定的,微软会持续做算法优化。
多数堆(像c-runtime堆)只要找到足够的空闲内存就分配给对象。因此,如果我连续分配多个对象时,这些对象的地址空间可能会相差几M。然而在托管堆上,连续分配的对象的内存地址是连续的。
前面的假设中还提到,新对象之间更可能存在相互引用关系。因此新对象分配到连续的内存上,你可以获得就近引用的性能优化(you gain performance from locality of reference)。这样的话很可能你的对象都在CPU的缓存中,这样CPU的很多操作就不需要去存取内存了。
微软的性能测试显示托管堆的分配速度比标准的win32 HeapAlloc方法还要快。这些测试也显示了200MHz的Pentium的CPU做一次0代回收时间可以小于1毫秒。微软的优化目的是让垃圾回收耗用的时间小于一次普通的页面错误。
使用System.GC类控制垃圾回收
类型System.GC运行开发人员直接控制垃圾回收器。你可以通过GC.MaxGeneration属性获得GC的最高代数,目前最高代是定值2.

你可以调用GC.Collect()方法强制垃圾回收器做垃圾回收,Collect方法有两个重载:

void GC.Collect(Int32 generation)

void GC.Collect()
ログイン後にコピー

第一个方法允许你指定要回收那一代。你可以传0到GC.MaxGeneration的数字做参数,传0只做0代堆的回收,传1会回收1代和0代堆,而传2会回收整个托管堆。而无参数的方法调用GC.Collect(GC.MaxGeneration)相当于整个回收。

在通常情况下,不应该去调用GC.Collect方法;最好让垃圾回收器按照自己的算法判断什么时候该调用Collect方法。尽管如此,如果你确信比运行时更了解什么时候该做垃圾回收,你就可以调用Collect方法去做回收。比如说程序可以在保存数据文件之后做一次垃圾回收。比如你的程序刚刚用完一个长度为10000的大数组,你不再需要他了,就可以把它设置为null然后执行垃圾回收,缓解内存的压力。
GC还提供了WaitForPendingFinalizers方法。这个方法简单的挂起执行线程,知道Freachable队列中的清空之后,执行完所有队列中的Finalize方法之后才继续执行。
GC还提供了两个方法用来返回某个对象是几代对象,他们是


Int32 GC.GetGeneration(object o);

Int32 GC.GetGeneration(WeakReference wr)
ログイン後にコピー

第一个方法返回普通对象是几代,第二个方法返回弱引用对象的代数。

下面的代码可以帮助你理解代的意义:

private static void GenerationDemo() {
// Let's see how many generations the GCH supports (we know it's 2)
Display("Maximum GC generations: " + GC.MaxGeneration);

// Create a new BaseObj in the heap
GenObj obj = new GenObj("Generation");

// Since this object is newly created, it should be in generation 0
obj.DisplayGeneration(); // Displays 0

// Performing a garbage collection promotes the object's generation
GC.Collect();
obj.DisplayGeneration(); // Displays 1

GC.Collect();
obj.DisplayGeneration(); // Displays 2

GC.Collect();
obj.DisplayGeneration(); // Displays 2 (max generation)

obj = null; // Destroy the strong reference to this object

GC.Collect(0); // Collect objects in generation 0
GC.WaitForPendingFinalizers(); // We should see nothing

GC.Collect(1); // Collect objects in generation 1
GC.WaitForPendingFinalizers(); // We should see nothing

GC.Collect(2); // Same as Collect()
GC.WaitForPendingFinalizers(); // Now, we should see the Finalize 
// method run

Display(-1, "Demo stop: Understanding Generations.", 0);
}
class GenObj{
public void DisplayGeneration(){
Console.WriteLine(“my generation is ” + GC.GetGeneration(this));
}

~GenObj(){
Console.WriteLine(“My Finalize method called”);
}
}
ログイン後にコピー

垃圾回收机制的多线程性能优化

前編では、GCアルゴリズムと最適化について説明しましたが、議論の前提はシングルスレッドの状況でした。実際のプログラムでは、複数のスレッドが連携して動作し、複数のスレッドがマネージド ヒープ上のオブジェクトを一緒に操作することがよくあります。スレッドがガベージ コレクションをトリガーすると、ガベージ コレクターがオブジェクトを移動し、オブジェクトのメモリ アドレスを変更する可能性があるため、他のすべてのスレッドは参照されたオブジェクト (独自のスタックで参照されるオブジェクトを含む) へのアクセスを一時停止する必要があります。
そのため、ガベージ コレクターがリサイクルを開始すると、マネージド コードを実行しているすべてのスレッドがハングする必要があります。ランタイムには、スレッドを安全に一時停止してガベージ コレクションを実行するためのさまざまなメカニズムがいくつかあります。この作品の内部メカニズムについては詳しく説明しません。ただし、Microsoft は、ガベージ コレクションによるパフォーマンスの低下を軽減するために、ガベージ コレクション メカニズムの変更を継続する予定です。
次の段落では、マルチスレッド状況でガベージ コレクターがどのように動作するかを説明します。
コードの実行を完全に中断します。ガベージ コレクションの実行が開始されると、すべてのアプリケーション スレッドが一時停止されます。次に、ガベージ コレクターは、スレッドの一時停止位置をジャストインタイム (JIT) コンパイラーによって生成されたテーブルに記録し、テーブル内でスレッドの一時停止位置を記録し、現在アクセスされているオブジェクトとその場所を記録します。オブジェクトが格納されている場所 (変数、CPU レジスタなど)
ハイジャック: ガベージ コレクターはスレッドのスタックを変更して、戻りアドレスが特別なメソッドを指すようにすることができます。現在実行されているメソッドが戻ると、この特別なメソッドは実行されます。スレッドを一時停止する このようにスレッドの実行パスを変更する方法をスレッドのハイジャックと呼びます。ガベージ コレクションが完了すると、スレッドは以前に実行されたメソッドに戻ります。
安全性のポイント: JIT コンパイラーがメソッドをコンパイルするときに、特定のポイントにコードを挿入して、GC がハングしているかどうかを判断できます。ハングしている場合、スレッドはガベージ コレクションが完了するのを待ってハングし、その後、スレッドは実行を再開します。 。 JIT コンパイラーが GC コードのチェックを挿入する場所は、「セーフ ポイント」と呼ばれます
スレッド ハイジャックにより、アンマネージ コードを実行しているスレッドがガベージ コレクション中に実行される可能性があることに注意してください。アンマネージ コードがマネージ ヒープ上のオブジェクトにアクセスしない場合、これは問題になりません。このスレッドが現在アンマネージ コードを実行しており、その後マネージ コードの実行に戻ると、スレッドはハイジャックされ、ガベージ コレクションが完了するまで実行を続行できません。
先ほど述べた集中化メカニズムに加えて、ガベージ コレクターには、マルチスレッド プログラムでのオブジェクト メモリの割り当てとリサイクルを強化するためのその他の改良点があります。
同期不要の割り当て: マルチスレッド システムでは、第 0 世代のヒープがいくつかの領域に分割され、1 つのスレッドが 1 つの領域を使用します。これにより、1 つのスレッドがヒープを排他的に所有する必要がなく、複数のスレッドがオブジェクトを同時に割り当てることができます。
スケーラブルなコレクション: マルチスレッド システムでサーバー バージョンの実行エンジン (MXSorSvr.dll) を実行します。マネージド ヒープは、CPU ごとに 1 つずつ、複数の異なる領域に分割されます。リサイクルが初期化されると、各 CPU はリサイクル スレッドを実行し、各スレッドは独自の領域を再利用します。ワークステーション バージョンの実行エンジン (MXCorWks.dll) は、この機能をサポートしていません。
ラージ オブジェクトのリサイクル
このセクションは翻訳されません。これについては特別な記事があります
ガベージ コレクションの監視
.Net Framework をインストールしている場合は、パフォーマンス カウンター ([スタート] メニュー - 管理ツール - パフォーマンス Enter) が表示されます。以下の図に示すように、インスタンス リストから監視するプログラムを選択できます。



これらのパフォーマンス指標の具体的な意味は次のとおりです。

パフォーマンス カウンター

説明

# すべてのヒープ内のバイト数

次のカウンター値の合計を表示します: "レベル 0 ヒープ サイズ カウンター、レベル 1ヒープ サイズ カウンタ、レベル 2 ヒープ サイズ カウンター、およびラージ オブジェクト ヒープ サイズ カウンター。このカウンターは、ガベージ コレクション ヒープに割り当てられている現在のメモリをバイト単位で示します。

# GC Handles (GC ハンドルの数)

現在使用されているガベージ コレクション ハンドルの数を表示します。ガベージ コレクションは、共通言語ランタイムおよびホスティング環境の外部にあるリソースの処理です。

# Gen 0 Collections (Level 2 Collections)

アプリケーションの開始以来、Gen 0 オブジェクト (つまり、最も新しく、最も最近割り当てられたオブジェクト) がガベージ コレクションされた回数を示します。

レベル 0 のガベージ コレクションは、割り当て要求を満たすためにレベル 0 で利用可能なメモリが不十分な場合に発生します。このカウンタは、レベル 0 のガベージ コレクションの終了時に増加します。上位レベルのガベージ コレクションには、下位レベルのすべてのガベージ コレクションが含まれます。このカウンタは、より高いレベル (レベル 1 またはレベル 2) のガベージ コレクションが発生すると、明示的にインクリメントされます。

このカウンターは、最新の観測値を示します。 _Global_ カウンタ値は不正確なので、無視する必要があります。

# Gen 1 Collections

アプリケーションの開始以降のレベル 1 オブジェクトのガベージ コレクションの数を表示します。

このカウンターは、レベル 1 ガベージ コレクションの終了時に増加します。上位レベルのガベージ コレクションには、下位レベルのすべてのガベージ コレクションが含まれます。このカウンタは、より高いレベル (レベル 2) のガベージ コレクションが発生すると明示的にインクリメントされます。

このカウンターは、最新の観測値を示します。 _Global_ カウンタ値は不正確なので、無視する必要があります。

# Gen 2 Collections

アプリケーションの起動以来、Gen 2 オブジェクトがガベージ コレクションされた回数を示します。このカウンタは、レベル 2 ガベージ コレクション (フル ガベージ コレクションとも呼ばれます) の終了時に増加します。

このカウンターは、最新の観測値を示します。 _Global_ カウンタ値は不正確なので、無視する必要があります。

# Induced GC (誘発された GC の数)

GC.Collect への明示的な呼び出しにより実行されたガベージ コレクションのピーク数を示します。ガベージ コレクターにコレクションの頻度を微調整させるのが現実的です。

# of Pinned Objects

最後のガベージ コレクションで検出された固定オブジェクトの数を表示します。ピン留めされたオブジェクトは、ガベージ コレクターがメモリに移動できないオブジェクトです。このカウンターは、ガベージ コレクションが行われているヒープ内の固定オブジェクトのみを追跡します。たとえば、レベル 0 のガベージ コレクションでは、レベル 0 ヒープ内の固定オブジェクトのみが列挙されます。

# of Sink Blocks in use

現在使用中の同期ブロックの数を表示します。同期ブロックは、同期情報を格納するために割り当てられたオブジェクトベースのデータ構造です。同期ブロックは管理オブジェクトへの弱い参照を保持するため、ガベージ コレクターによってスキャンする必要があります。同期ブロックは同期情報のみを保存することに限定されず、COM 相互運用メタデータも保存できます。このカウンタは、同期プリミティブの過剰使用に関連するパフォーマンスの問題を示します。

# Total Committed Bytes

ガベージ コレクターによって現在コミットされている仮想メモリの量 (バイト単位) を示します。コミットされたメモリは、ディスク ページング ファイルに予約された領域の物理メモリです。

# Total Reserved Bytes

ガベージ コレクターによって現在予約されている仮想メモリの量 (バイト単位) を示します。予約メモリは、アプリケーション用に予約されている仮想メモリ領域です (ただし、ディスクやメイン メモリ ページはまだ使用されていません)。

% GC の時間 (GC の時間の %)

最後のガベージ コレクション サイクル以降、ガベージ コレクションの実行に費やされた実行時間の割合を示します。このカウンターは通常、アプリケーションに代わってガベージ コレクターがメモリを収集して圧縮する作業を示します。このカウンタは、各ガベージ コレクションの終了時にのみ更新されます。このカウンターは平均ではなく、その値は最新の観測値を反映しています。

Allocated Bytes/sec (割り当てられたバイト/秒)

1 秒あたりにガベージ コレクション ヒープに割り当てられたバイト数を表示します。このカウンタは、割り当てごとではなく、ガベージ コレクションの終了時に更新されます。このカウンターは時間の経過に伴う平均ではなく、最近の 2 つのサンプルで観察された値の差をサンプル間の時間で割って表示します。

Finalization Survivors (完了時に残っているオブジェクトの数)

完了を待っているためにコレクションから保持されているガベージコレクションされたオブジェクトの数を表示します。これらのオブジェクトが他のオブジェクトへの参照を保持している場合、それらのオブジェクトは保持されますが、このカウンタではカウントされません。 Completion Memory Promoted from Level 0 および Completion Memory Promoted from Level 1 カウンターは、完了によって保持されたすべてのメモリを表します。

このカウンターは累積的なカウンターではなく、各ガベージ コレクションの終了時に、その特定のコレクション中にのみ生き残ったオブジェクトの数によって更新されます。このカウンタは、アプリケーションの完了により過剰なシステム オーバーヘッドが発生する可能性があることを示します。

Gen 0 ヒープ サイズ (レベル 2 ヒープ サイズ)

レベル 0 に割り当てられる最大バイト数を示します。レベル 0 に割り当てられている現在のバイト数を示すものではありません。

レベル 0 のガベージ コレクションは、最新のコレクション以降の割り当てがこのサイズを超えた場合に発生します。レベル 0 のサイズはガベージ コレクターによって微調整され、アプリケーションの実行中に変更される可能性があります。レベル 0 のコレクションの終了時点では、レベル 0 のヒープのサイズは 0 バイトです。このカウンターは、次のレベル 0 ガベージ コレクションを呼び出す割り当てのサイズをバイト単位で示します。

このカウンタは、ガベージ コレクションの終了時に更新されます (割り当てごとではありません)。

Gen 0 Promoted Bytes/Sec (レベル 1 からプロモートされたバイト数/秒)

レベル 0 からレベル 1 にプロモートされた 1 秒あたりのバイト数を表示します。メモリはガベージ コレクションから保持された後に昇格されます。このカウンタは、1 秒あたりに作成され、長期間保持されているオブジェクトの数を示します。

このカウンターは、最後の 2 つのサンプルで観察された値の差をサンプリング間隔の期間で割った値を示します。

Gen 1 ヒープ サイズ (レベル 2 ヒープ サイズ)

レベル 1 の現在のバイト数を示します。このカウンターはレベル 1 の最大サイズを示しません。この世代では、オブジェクトは直接割り当てられません。これらのオブジェクトは、以前のレベル 0 ガベージ コレクションから昇格されます。このカウンタは、ガベージ コレクションの終了時に (割り当てごとではなく) 更新されます。

Gen 1 Promoted Bytes/Sec (レベル 1 から昇格されたバイト数/秒)

レベル 1 からレベル 2 に昇格された 1 秒あたりのバイト数を示します。単に完了を待っているという理由で昇格されたオブジェクトは、このカウンタには含まれません。

メモリはガベージコレクションから保存された後に昇格されます。レベル 2 は最も古いレベルであるため、レベル 2 からの昇格はありません。このカウンタは、1 秒あたりに作成される非常に寿命の長いオブジェクトの指標です。

このカウンターは、最後の 2 つのサンプルで観察された値の差をサンプリング間隔の期間で割った値を示します。

Gen 2 ヒープ サイズ

レベル 2 の現在のバイト数を示します。オブジェクトはこの世代では直接割り当てられません。これらのオブジェクトは、前のレベル 1 ガベージ コレクション中にレベル 1 から昇格されました。このカウンタは、ガベージ コレクションの終了時に (割り当てごとではなく) 更新されます。

ラージ オブジェクト ヒープ サイズ

ラージ オブジェクト ヒープの現在のサイズをバイト単位で表示します。ガベージ コレクターは、20 KB を超えるオブジェクトをラージ オブジェクトとして扱い、これらのレベルを介して昇格されないラージ オブジェクトを特別なヒープに直接割り当てます。このカウンタは、ガベージ コレクションの終了時に (割り当てごとではなく) 更新されます。

Gen 0 から昇格した Finalization-Memory (レベル 1 から昇格した完了メモリ)

完了を待機しているためだけにレベル 0 からレベル 1 に昇格したメモリのバイト数を示します。このカウンタは累積カウンタではなく、最後のガベージ コレクションの終了時に観測された値を示します。

プロモートされたファイナライゼーション - 第 1 世代からのメモリ

単に完了を待っているためにレベル 1 からレベル 2 に昇格したメモリのバイト数を示します。このカウンタは累積カウンタではなく、最後のガベージ コレクションの終了時に観測された値を示します。最後のガベージ コレクションがレベル 0 コレクションだった場合、このカウンターは 0 にリセットされます。

Gen 0 からプロモートされたメモリ (Gen 1 からプロモートされたメモリ)

ガベージ コレクション後に保持され、Gen 0 から Gen 1 にプロモートされたメモリのバイト数を示します。完了を待っている間にのみ発生するオブジェクトは、このカウンタから除外されます。このカウンタは累積カウンタではなく、最後のガベージ コレクションの終了時に観測された値を示します。

Gen 1 からプロモートされたメモリ (Gen 1 からプロモートされたメモリ)

ガベージ コレクション後に保持され、Gen 1 から Gen 2 にプロモートされたメモリのバイト数を示します。完了を待っている間にのみ発生するオブジェクトは、このカウンタから除外されます。このカウンタは累積カウンタではなく、最後のガベージ コレクションの終了時に観測された値を示します。最後のガベージ コレクションがレベル 0 コレクションだった場合、このカウンターは 0 にリセットされます。

この表は MSDN から引用しています

上記は .Net ガベージ コレクション メカニズムの原則 (2) の内容です。さらに関連する内容については、PHP 中国語 Web サイト (www.php.cn) に注目してください。


ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート