.NETガベージコレクションの第2章のために-----書き込み高性能コード

ガーベジコレクション

メモリは常に、通常はない、またはお店の数が比較的小さな増加膨張波よりも全体的に割り当てられたメモリそのため、.NET環境では、メモリ割り当てのワークロードは、非常に小さいです。通常の状況下では、あなたが存在しない空きメモリのリストをトラバースする必要がある、メモリの断片化が発生することはほとんど不可能です。実際には、ヒープに割り当てられた行の複数のオブジェクトがしばしば可能に最も近いアクセス(局所性)を上げる、行に格納されているため、より高い効率のGCヒープ。デフォルトのメモリ割り当て処理では、対象物のサイズを確認するためのコードのビットが存在することになる、使用にも十分なメモリバッファの残りのメモリ割り当てを見てみます。限り、バッファに十分なメモリ割り当てプロセスを持っているとして、リソースの競合の問題は非常に急速です。メモリバッファの割り当てが枯渇した場合、ターゲットオブジェクトを取得するために、交流配電プログラムに引き渡される空きメモリを保持するのに十分な大きさです。そして、それは将来のメモリ割り当てのために保存される新しいバッファを割り当てます。上記のアセンブリコードは、単にメモリ割り当てプロセスである - 命令コード分析の小片は貴重です。C#コードは、次のように単純なメモリ割り当てプロセスが実証しています。

c1ass  Myobject{
    int x:
    int y:
    int 
}

static void Main(string[] args)
{
    var x = new Myobject();
}

まずは、それを打破しましょう。以下は、メモリ割り当て関数の呼び出しコードです。

以下は、実際の分布関数です。

要するに、上記のプロセスは、唯一の直接メソッド呼び出しと9つの指示をしました。無原罪、非の打ちどころのありません。あなたのガベージコレクションは、サーバーモードを設定した場合、各プロセッサは、自身のメモリヒープを持っているので、メモリ割り当てプロセスは、高速と低速のポイントではありません。.NETメモリ割り当てプロセスは比較的単純で、割り当て解除プロセスは、はるかに複雑であるが、複雑なプロセスが直接対処する必要はありません。あなただけであること、最適化する方法を学ぶ必要がある、この章では、あなたに教えます
コンテンツを。スタートガベージコレクションから、この本は、ので、コンテンツの多くのフォローアップは、この章に関連付けられます理由。プログラムの影響を理解するために、ガベージコレクタが所望の性能を達成するための重要な基盤であり、ガベージコレクタは、ほぼすべての他のパフォーマンス要因に影響を与えます。


どのように動作する2.1

ガベージコレクタの意思決定プロセスは、特に採用され、ますます人気の高性能システムで、より多くのエレガントになってきている
.NET環境で。いくつかは、NETの将来のバージョンで変更されますが、最も最近の期間を変更します以下の整合性を持っているようだ-以下の導入が持っていることがあります。管理されたプロセスに2つのメモリヒープ(マネージヒープとネイティブヒープ)があります。マシン・ヒープ(ネイティブヒープ)は、VirtualAllocのWindowsのAPIによって割り振られ、システムのデータ構造、多くのCLRデータを操作する、などのWindows APIとして、アンマネージコードメモリのために必要な、オペレーティングシステムとCLRによって使用されます。オブジェクトがコントロールのガベージコレクションの対象となっているため、すべての.NET管理対象オブジェクトのマネージヒープ(マネージヒープ)のCLRは、また、GCヒープとして知られている、メモリを割り当てられました。管理ヒープは、二つの小さなオブジェクトのヒープとラージオブジェクトヒープ(LOH)に分け、両方の独自のメモリ・セグメント(セグメント)を有しています。大規模なプログラムがMBの数百以上とすることができるため、ハードウェア環境のサイズおよび構成に応じて、各メモリ・セグメントは、であってもよいです。小さなオブジェクトヒープLOHと複数のメモリセグメントを有することができます。さらに三世代、すなわち0,1,2世代に分け- -小さなは、ヒープメモリセグメントにオブジェクト。0世代1世代と常に同じメモリセグメントに位置し、第二世代は、複数のメモリセグメントにまたがることが、LOHの複数のメモリセグメントにまたがることができます。第0及び第1世代生成ヒープメモリセグメントは、一時セグメント(エフェメラルセグメント)と呼ばれます。小から大へ、右メモリアドレスに左から以下に示す開始ヒープは、二つのメモリセグメントは、AおよびBとラベル付けされています。小さなオブジェクトヒープメモリ構成のセグメント、LOHは、メモリのB部を有しています。彼らは空であるため、第2世代および第一世代は、少しヒープメモリの始まりを持っています。


 

ここでは、ヒープメモリに割り当てられたオブジェクト内の小さなオブジェクトの生存を導入する必要があります。オブジェクトが85,000バイト未満である場合、それは通常、次の現在使用されているメモリ空間に割り当てられたバックに小さなオブジェクトのCLR世代0ヒープを割り当てられます。この章の最初に示したようにこのように、.NETメモリ割り当てプロセスは非常に高速です。迅速な割り当てが失敗した場合、オブジェクトは、長いラインを収容するのに十分なほど、どこでも人々の世代0ヒープメモリを配置することができます。いいえ、適切な空き領域場合は、人々が新しいオブジェクトを保存することができますように、そして販売代理店は、世代0ヒープを拡大していきます。メモリヒープを拡張した場合、メモリ・セグメントの境界を越えて、ガベージコレクションがトリガされます。オブジェクトは常に世代0ヒープに生まれています。限り、オブジェクトが生きているままで、ガベージコレクションが発生するたびに、GCはそれを世代を発生させます。ジェネレーション0と第一世代のガベージコレクションヒープメモリは時々、瞬間回復(EphemeralCollection)と呼ばれています。ガベージコレクションのイベントでは、あなたが(圧縮)をデフラグも、GCは、物理的なオブジェクトがメモリ・セグメント内の空きスペースができるまで連続して使用できる状態にできるようにするために行くために新しい場所に移動しています。デフラグが発生しない場合は、それだけで、各メモリブロックの境界を再調整する必要があるだろうことができます。デフラグのガベージコレクションをせずに数回した後、分散メモリヒープは、次のようになります。

オブジェクトの位置が移動するのではなく、メモリヒープの世代の境界が変更されました。各世代が起こりヒープデフラグする可能性があります。彼らは新しい場所を指すようにデフラグは比較的高価であり、すべての管理対象のスレッドを中断する必要がある場合がありますので、GCは、オブジェクトへのすべての参照を修正する必要があるため。これにより、ガベージコレクタは、デフラグするときに費用対効果(生産性)、いくつかの内部の指標の判断に従って。オブジェクトは、第二世代のメモリヒープに到達することであるならば、それは常に最後までそこに残ります。これは、第二世代のみヒープが増加しているという意味ではありません。メモリヒープオブジェクトの第二世代が終了している場合は、全体のメモリ・セグメントではなく、ライブオブジェクト、ガベージコレクタは全体のメモリ・セグメント・オペレーティング・システムを返済、または他の世代のメモリヒープの追加セグメントとしてでしょうがなかったです。フルガベージコレクション(フルガベージコレクション)が行われた場合、メモリヒープのこの第二世代の回復が発生する可能性があります。その後、GCは、いずれかを渡すことができれば、それは何を意味する「ライブ」 - ? - GCのルートオブジェクト(ルート)、層に沿った基準を知られているオブジェクトへのアクセスは、それが生き残るためにです。GCルートオブジェクトは、静的変数のプログラムであってもよく、またはスレッド・スタックは、(ローカル変数に)実行方法によって占有されている、又はGCハンドル(固定ハンドル例えばオブジェクト、固定ハンドル)、またはキューの末尾(ファイナライザキュー)。フルガベージコレクションがにクリーンアップされるまで、あなたは待つ必要があり、いくつかのオブジェクトがGCのルートオブジェクトによって参照されない場合があることに注意が、それは第二世代のメモリヒープ上に配置されている場合、その世代0回復は、これらのオブジェクトをクリーンアップするつもりはないしてください。第一世代0ヒープは、メモリ・セグメント、およびガベージコレクタを埋めるしようとしている場合は、GCをデフラグすることにより、十分な空きメモリを得ることができない、新しいメモリセグメントを割り当てます。新たなメモリセグメントは、第二のスタックの古い世代に変わる第一世代及び第二世代0ヒープメモリセグメントを受信するために使用されます。古い世代0ヒープ内のすべてのオブジェクトを新たな第一世代のヒープ内に配置され、古い第一世代の原子炉は、(データをコピーすることなく、容易にリフト)第二世代ヒープの共感を増加させるであろう。メモリ・セグメントは現在、以下のだろう。

 

第二世代が大きくパイルし続ける場合には、複数のメモリセグメントにまたがることができます。LOHは、複数のヒープメモリセグメントにまたがることができます。多数のメモリセグメントが存在するかに関係なく、世代0と世代1は、常に同じセグメント内に配置されています。私たちが何をオブジェクトヒープメモリが生きているのを確認したいときその後、この知識は便利になるだろう。LOHリカバリ・ルールの別のセットに従ってください。オブジェクトバイト85,000より大きい、自動的LOHに割り当てメモリ、およびno「世代」モードです。このサイズのオブジェクトよりは、通常の文字列との配列です。パフォーマンス上の理由から、LOHは、自動的にガベージコレクション中にデフラグされていませんが、.NET 4.5.1スタートは、必要に応じて、あなたはまた、人為的にデフラグを開始することができます。同様に第二世代のメモリヒープ、LOHのメモリはもはや有用ではない場合、それは他のメモリヒープのために使用することができます。しかし、将来的には、理想的には、あなたがLOHがメモリ不足に回復させて喜んでではないでしょう、表示されます。LOHでは、ガベージコレクションは、オブジェクトの空きメモリの保管場所のリストを決定するために使用します。この章では、断片化のLOHを減らすためにいくつかのヒントについて説明します。

Taがごみリサイクルのためにある - ヒープと、次の世代に代わって行って - 第一世代の回復した場合、世代0も回復します。第二世代の回復した場合、すべてのヒープメモリは、LOHを備え、回収されます。第一世代の0または0.1世代別ガベージコレクションが発生した場合、プログラムは回復操作中に中断されます。第二世代のガベージコレクションのために、コンフィギュレーションパラメータに基づいている必要があり、バックグラウンドスレッドで実行される回復の一部があります。

ガベージコレクションは、四つの段階を含んでいます。
ガベージコレクションが発生する前に、すべての管理対象のスレッドが強制的に中止された(サスペンション)サスペンド1.。
2.マークルートオブジェクトの先頭から(商標)GC、全ての参照オブジェクトと記録見物体に沿ってガベージコレクタを通過します。
3.デフラグ(コンパクト)が再び標的次格納することと、メモリフラグメンテーションを低減するために、すべての参照を更新します。ヒープ上の小さなオブジェクトでは、オンデマンドでデフラグは、あなたがコントロールすることはできません。LOHでは、デフラグは自動ではありませんが、必要に応じて、あなたはに、ガベージコレクタに気づくことができます- -回。
運転を再開するマネージスレッド- 4.(再開)Aを復元します。マーク・フェーズでは限り、あなたは回復するために、それらの必要性の一部にアクセスすることができますよう、ヒープ内のすべてのオブジェクトをトラバースする必要はありません。より
世代0回復は世代0ヒープのオブジェクトのみ、メモリー・ヒープのオブジェクトの生成0と世代をマークする第一世代の回収を必要とするよう。第二世代の回復と完全な回復、我々はこの、すべての生きているオブジェクトヒープメモリを通過する必要がある-プロセスのコストが非常に大きくなる可能性があります。小さな問題に注意が必要な、ヒープ内のメモリ・オブジェクトの高い世代がメモリヒープオブジェクトのルートオブジェクト低い世代かもしれあります。これは、メモリヒープオブジェクトの高い世代の横の部分にガベージコレクタが発生しますが、これはまだあまり高い世代のガベージコレクションヒープメモリのフルコスト回収を超えています。

上記のいくつかの重要な結論によって以下に形成することができます。
まず、ガベージコレクションの時間のかかるプロセスではなく、あなたが割り当てられていることをオブジェクトの数よりも、関係するメモリヒープ「に代わって」オブジェクトの数にほぼ完全に依存しています。あなたは木を割り当てた場合でも、この手段は百万オブジェクト、限り百万オブジェクトは、時間のかかるガベージコレクションを増加させない次のガベージコレクションルートオブジェクトリフトオフの前に引用符が含まれています。
「世代を」関与ガベージコレクションの頻度に応じて、第二には、ヒープメモリのサイズとなっています。割り当てられたメモリは、「世代」ガベージコレクションの内部特定の閾値を超える長いほど発生します。このしきい値は絶えず変化して、GCは、実装方法に応じて調整されるであろう。「世代」回復費用対効果は十分(「世代」の中にたくさんのオブジェクトを改善)した場合、そのガベージコレクションが頻繁に発生します- 、およびその逆。ガベージコレクションをトリガするもう一つの要因は関係なく、あなたのアプリケーションの、すべての利用可能なメモリです。利用可能なメモリが所定の閾値未満である場合、全体のメモリ・ヒープのサイズを低減するために、ガベージコレクションがより頻繁に起こり得ます。
以上のことから、ガベージコレクションを制御することは、一見難しいですが、それはそうではありません。メモリ割り当てモード制御制御することにより
、統計的な指標のガベージコレクションのシステムを、最適化の方法は、達成するのが最も簡単なの一つです。これは、ガベージコレクションの作業メカニズムを理解する必要が
あり、設定パラメータは、お使いのメモリ割り当て率は、また、オブジェクトの寿命にわたって良好な制御を持っている必要があります。


2.2設定パラメータ

2.2.1ワークステーションモードまたはサーバモード
 

最も重要なパラメータのオプションは、ガベージコレクションのワークステーション(ワークステーション)モードまたはサーバ(サーバ)モードを使用することです。ガベージコレクション局モードをデフォルトとします。ワークステーションモードでは、トリガガベージコレクションスレッドの優先順位(優先度)に実行されるすべてのGCは同じです。ワークステーションは、理想的に単純なアプリケーション、マンマシン対話型のワークステーション(インタラクティブ・ワークステーション)で実行して特に適している。複数のホストプロセスで上位の実行上のアプリケーション、マシンを。シングルプロセッサコンピュータの場合は、ワークステーションモデルが唯一の選択肢である、他の設定されたパラメータは無効です。サーバモードでは、GCは、各論理プロセッサまたはプロセッサコアのために専用のスレッドを作成します。これらの優先順位のスレッドが最高(最高THREAD_ PRIORITY_)ですが、ガベージコレクションの前にする必要があります - - ストレート遺骨が保留中。ガベージコレクションが完了すると、スレッドが再びスリープ(スリープ)状態になります。また、CLRは、各プロセッサのための別個のヒープメモリを作成します。各プロセッサは、スタックと小さなオブジェクトヒープのLOHが含まれています。アプリケーションの観点からは、唯一の論理的なメモリヒープがあり、あなたのコードは、ヒープに属するオブジェクトは不明である、オブジェクト参照がすべてのスタックの間(これらの文献は、同一の仮想アドレス空間を共有する)のクロスになります。

複数のメモリヒープは、いくつかの利点をもたらすでしょう。
ヒープ- 1.ガベージコレクションを並列に実行することができ、各スレッドは、ガベージコレクションをリサイクルする責任があります。これは、大幅に高速ワークステーションモードよりもガベージコレクションすることができます。
-いくつかの、特にLOHの面で、それはすべてのヒープで同時に配布されますので、 - 2.いくつかのケースでは、メモリ割り当ての速度が速くなります。もう一つのポイントはサーバモードとワークステーションモードの異なるガベージコレクションの間隔が長くなることを意味しており、我々はより多くのメモリ・セグメントを持っていることである-いくつか。
してください<ランタイム>ノードapp.configファイルごみDHCPサーバモードの時。

<configuration>
    <runtime>
        <gcServer enabled="true"/>
    </ runtime>
</configuration>

アプリケーションは、マルチプロセッサホスト上で、あなたの準備を実行するために設計されている場合は最終的には?ワークステーションやサーバモデルとガベージコレクションである。上で、それは間違いなく、サーバーモードを選ぶだろう。だから、ほとんどの場合、ガベージコレクションを最小限に時間がかかることができます。あなたが複数のホストプロセスでホストを共有する必要がある場合は、次の選択がそれほど明確ではありません。ガベージコレクションサーバーモードでは、複数の優先度の高いスレッドを作成します。複数のアプリケーションが設定されている場合はそのスレッドスケジューラは、互いに悪影響を及ぼされることを。そして、あなたはまだ、より良いワークステーションのガベージコレクションモードを選択することができます。あなたが本当にガベージコレクションを使用して、サーバーモードで同じホストで複数のアプリケーションを使用する場合は、そこにある - 実際には競合が実行されているいくつかの指定されたプロセッサに集中していることアプリケーションを可能にすることです、CLRので、このため、独自のメモリヒープを作成します。これらのプロセッサを。あなたが選択した方法に関係なく、ガベージコレクションモードの両方のために、この本の中で与えられたヒントのほとんどが適用されます。
 

2.2.2バックグラウンドガベージコレクション
 

背景ガベージコレクション(GC背景は)唯一の第二世代のガベージコレクションヒープメモリの動作に影響を与えます。世代0と世代1ガベージコレクションは、あるフォアグラウンドのガベージコレクションを、採用する全てのアプリケーションスレッドをブロックします。ガベージコレクションスレッドの専用の第二世代バックグラウンドのガベージコレクションが完了します。ガベージコレクションサーバモードの場合は、各論理プロセッサが持っている - 追加のバックグラウンドGCスレッドを。はい、各プロセッサは2つの専用GCスレッドが、特別な注目に値する何を持っていますサーバモードのガベージコレクションとバックグラウンドガベージコレクションであれば、そのことは、この意味。これは、複数のスレッドが最も特にほとんどの操作を行うための時間は何ものスレッドで、プロセスの任意の大きな負担にはなりません持っています。バックグラウンドガベージコレクション、アプリケーションが並行して発生スレッドが、また、ブロッキングガベージコレクションが発生する可能性があります。このとき、バックグラウンドGCスレッドと他のアプリケーションスレッドが一緒にガベージコレクションを遮断するの完了を待って、一時停止します。あなたは、ワークステーションのガベージコレクションモードになりますバックグラウンドガベージコレクションを使用している場合 - - まっすぐに。.NET 4.5以降では、バックグラウンドのガベージコレクションでサーバモードのガベージコレクションは、デフォルトで有効になっていますが、それでも閉じることができます。次の設定は、バックグラウンドのガベージコレクションをオフにします。

<configuration>
    <runtime>
        <gcConcurrent enabled="false"/>
    </ runtime>
</ confi guration>

 

実用的なアプリケーションでは、バックグラウンドのガベージコレクションをオフにする理由はほとんどがあるでしょう。あなたがバックグラウンドガベージコレクション停止する場合は
、スレッドを多用するアプリケーションのためのCPU時間を、時間を気にしない、完全なガベージコレクションとガベージコレクションの閉塞時に増加する
間および周波数を、それはそれをやってのけることができます。
2.2.3低レイテンシモード(低レイテンシモード)

あなたが一定の期間にわたって高性能を確保する必要がある場合は-Iは、GC通知かなりのオーバーヘッドジェネレーション2ガベージコレクションを実行することはできません。GCSettings.LatencyModeは、他のパラメータに応じて次のプロパティの値のいずれかを割り当てることができます。第二世代のガベージコレクションを禁止するだけでGC用LowLatency--局モード、。
完全に第二世代のガベージコレクションを禁止●SustainedLowLatency適したワークステーションとGCサーバモードが、バックグラウンドのガベージコレクションの第二世代を可能にします。あなたを有効にするには、このパラメータをバックグラウンドガベージコレクションを有効にする必要があります。デフラグされることはありませんので、ので、これら2つのパラメータが大幅にマネージヒープのサイズが大きくなります。メモリのあなたのプロセス要件場合は、この低遅延モードを使用しないでください。低レイテンシモードに入ってくる前に、それは完全なガベージコレクションを強制するのが最善である、これが完了するGC.Collect(2、GCCollectionMode .Forced)を呼び出すことによって。コードは、低遅延モードを終了するときは、すぐにそれを行う-完全なガベージコレクションの時間を。デフォルトモードとして、低レイテンシモードを使用しないでください。低レイテンシモードが長時間中断してはいけませんこれらのアプリケーションのために実際にあるが、時間のない100%がケースに持っていました。良い例は、開口部の間に、当然のことながら、完全にガベージコレクションが発生したくない、Gupiaojiaoyiです。閉じられた時に、あなたは、低遅延モードをオフにし、フルバックのガベージ実行することができ
、次回まで市場が開かれた後、スイッチバック、コレクションを。以下の条件は、低遅延モードを開くために満たされた場合にのみ。ガベージコレクションの期間は、完全長すぎる、プログラムの通常の操作は絶対に容認できません。アプリケーションのメモリフットプリントは、使用可能なメモリの数よりもはるかに低いです。それは低遅延モード中に閉じているかどうか、プログラムを再起動、または完全なガベージコレクションを手動で実行する時に、アプリケーションが実行可能な状態に保つことができます。

潜在的な不確実性、低レイテンシモードはほとんど使用されませんので、あなたはよく考えなければなりません。あなたは、このモードそれが役に立つ見つけた場合、性能評価は、必ず効果のようにします。それは副作用を引き起こすためのオープン低遅延モードでは、他のパフォーマンスの問題が発生することがあります。完全なガベージコレクションの不足に対応して、瞬間回復(世代0と世代1ガベージコレクション)頻度が増加します。あなたは可能性が高いとされている「ひょうたんが押さひしゃくを果たしました。」最後に、してくださいノートではなく、低レイテンシモードが - を反映することを保証することができるようになります。あなたは完全にアウトofMemoryExceptionの間の選択をリサイクルまたはスローにしたい場合は、ガベージコレクタが完全に回復することもできますので、あなたのセットは無効です。


メモリ割り当ての量を減らすために2.3

それはほとんどあなたがメモリのデフラグとCPU使用率の量を減らすことができ、またこれガベージコレクタの動作圧力を低下させる、メモリ割り当ての数を減らすことが、あればあることは言うまでもないです。メモリ割り当ての量を減らし、そしていくつかは、仕事を考え、そして他の設計目標と競合する可能性があります。慎重にそれぞれを検討-対象は、自問してみてください。
●本当にこのオブジェクトが必要?
●オブジェクトの任意のメンバーがそこに放棄することができていますか?
●配列は、の?(プリミティブ)プリミティブ型数を減らすことができ、ボリュームを減らすことができます(Int64のはのInt32を置き換えなど)?
●一部のオブジェクトをめったに?。再割り当て、必要なときだけ使用していないかどうか
●一部のクラスは、「構造」(構造体)になることができます?これはスタック上に保存され、またはその他のオブジェクトがなるために
メンバー。
多くのメモリを割り当て、ごく一部か?
他の方法でデータを取得することはできますか?
 

公開された37元の記事 ウォンの賞賛3 ビュー6323

おすすめ

転載: blog.csdn.net/huan13479195089/article/details/103842339