13

ネットワークからメッセージを受信し、メッセージの種類に応じて異なるオブジェクトに変換し、最後にアプリケーション ビジネス ロジックを適用する金融 C# アプリケーションを作成しています。

ポイントは、ビジネス ロジックが適用された後は、このインスタンスが再び必要になることはないと確信しているということです。ガベージコレクターがそれらを解放するのを待つのではなく、明示的に「削除」したいと思います。

オブジェクトのプールを使用して常に同じインスタンスのセットを再利用する必要がありますか、それともより良い戦略がありますか?

目標は、タイム クリティカルなプロセス中にガベージ コレクションが CPU を使用するのを回避することです。

4

13 に答える 13

22

それらをすぐに削除しないでください。オブジェクトごとにガベージ コレクタを呼び出すのは、お勧めできません。通常、ガベージ コレクターをいじりたくはありません。タイム クリティカルなプロセスでさえ、機密性が高い場合は競合状態が発生するのを待っています

ただし、アプリの負荷が高い期間と低い期間があることがわかっている場合は、軽い期間に達したときに、より一般的な GC.Collect() を試して、次の繁忙期の前にクリーンアップを促すことができます。

于 2008-09-17T16:57:07.213 に答える
18

ここを見てください:http://msdn.microsoft.com/en-us/library/bb384202.aspx

ガベージ コレクターに、現在重要なことを行っていることを伝えることができます。

于 2008-09-17T16:59:23.603 に答える
11

オブジェクトのプールを使用し、それらのオブジェクトを再利用します。これらのオブジェクトへの呼び出しのセマンティクスは、ファクトリ ファサードの背後に隠される必要があります。事前に定義された方法でプールを拡張する必要があります。おそらく、限界に達するたびにサイズを 2 倍にするでしょう。ハイウォーター アルゴリズム、または一定のパーセンテージです。GC.Collect() を呼び出さないことを強くお勧めします。

プールの負荷が十分に低くなると、プールを縮小でき、最終的にはガベージ コレクションがトリガーされます。CLR に心配させてください。

于 2008-09-17T17:35:14.110 に答える
7

一般に、ガベージ コレクタを推測しようとするのは非常に悪い考えです。Windows では、ガベージ コレクターは世代別のものであり、非常に効率的であると信頼できます。この一般的な規則にはいくつかの注目すべき例外があります。最も一般的なのは、オブジェクトが Gen2 (最長寿命) に昇格すると、多くの古いオブジェクトが死ぬ原因になることがわかっている 1 回限りのイベントの発生です。彼らはぶらぶらする傾向があります。

あなたが言及した場合、あなたは多くの短命のオブジェクトを生成しているように聞こえます-これらはGen0コレクションになります。いずれにせよ、これらは比較的頻繁に発生し、最も効率的です。必要に応じて、オブジェクトの再利用可能なプールを用意することでそれらを回避できますが、そのようなアクションを実行する前に、GC がパフォーマンスの問題であるかどうかを確認することをお勧めします。CLR プロファイラーは、これを行うためのツールです。

ガベージ コレクターは .NET フレームワークによって異なることに注意してください。コンパクトなフレームワーク (Xbox 360 およびモバイル プラットフォームで実行されます) では、ガベージ コレクターは非世代 GC であるため、何についてもっと注意する必要があります。プログラムが生成するガベージ。

于 2008-09-17T17:30:52.873 に答える
6

GC.Collect() を強制することは一般的に悪い考えです。必要に応じて拡張できるオブジェクトのプールを使用することが最善の解決策のように思えます-私はこのパターンをうまく使用しました。

このようにして、ガベージ コレクションだけでなく、通常の割り当てコストも回避できます。

最後に、GC が問題を引き起こしていると確信していますか? パフォーマンスを節約するソリューションを実装する前に、おそらくこれを測定して証明する必要があります-不要な作業を引き起こしている可能性があります!

于 2008-09-17T17:02:12.350 に答える
5

「目標は、タイムクリティカルなプロセス中にガベージコレクションがCPUを使用するのを避けることです」

Q:タイム クリティカルな場合、難解なハードウェアを聞いていて、割り込みを見逃すわけにはいかないということですか?

A:そうであれば、C# は使用する言語ではありません。そのためには、アセンブラー、C、または C++ が必要です。

Q:クリティカルとは、パイプに大量のメッセージがあり、ガベージ コレクターによって速度が低下するのを防ぎたいという意味ですか?

A:もしそうなら、あなたは不必要に心配しています。オブジェクトの寿命が非常に短いということは、ガベージ コレクターがそれらを非常に効率的にリサイクルし、パフォーマンスに明らかな遅延がないことを意味します。

ただし、確実に知る唯一の方法は、それをテストし、テスト メッセージの一定のストリームを処理するように一晩実行するように設定することです。GC が開始されたときにパフォーマンス統計を見つけることができれば、私は唖然とします (できたとしても)それが実際に重要な場合、私はさらに驚くでしょう)。

于 2009-02-09T17:09:24.577 に答える
3

ガベージコレクターがどのように動作するかをよく理解して感じてください。そうすれば、ここで考えていることが推奨されない理由を理解できます。CLRがメモリ内のオブジェクトの再配置に多くの時間を費やすのが本当に好きでない限り。

于 2008-09-17T17:10:23.967 に答える
3

アプリの負荷はどれくらいですか? 3 つのサウンド カード (マネージド DirectX、44.1KHz、ステレオ、16 ビット) を 8KB ブロックでキャプチャし、3 つのストリームのうち 2 つを TCP/IP 経由で別のコンピューターに送信するアプリを作成しました。UI は、オーディオ レベル メーターと (スムーズな) スクロール タイトル/アーティストを 3 つのチャンネルごとにレンダリングします。これは、XP、1.8GHz、512MB などの PC で実行されます。アプリは CPU の約 5% を使用します。

手動で GC メソッドを呼び出すことは避けました。しかし、無駄ないくつかのことを調整する必要がありました。RedGate の Ant プロファイラーを使用して、無駄な部分を絞り込みました。素晴らしいツールです!

事前に割り当てられたバイト配列のプールを使用したかったのですが、マネージド DX アセンブリが内部でバイト バッファーを割り当ててから、それをアプリに返します。する必要がないことがわかりました。

于 2008-10-18T03:25:31.933 に答える
2

絶対にタイムクリティカルな場合は、C /C++のような決定論的プラットフォームを使用する必要があります。GC.Collect()を呼び出しても、CPUサイクルが生成されます。

あなたの質問は、メモリを節約したいがオブジェクトを取り除きたいという提案から始まります。これはスペースクリティカルな最適化です。GCは人間よりもこの状況を最適化するのに優れているため、本当に必要なものを決定する必要があります。

于 2008-09-17T17:07:23.617 に答える
2

その音からすると、C#には存在しない決定論的ファイナライズ(C ++のデストラクタ)について話しているようです。C#で最も近いのは、Disposableパターンです。基本的に、IDisposableインターフェースを実装します。

基本的なパターンは次のとおりです。

public class MyClass: IDisposable
{
    private bool _disposed;

    public void Dispose()
    {
        Dispose( true );
        GC.SuppressFinalize( this );
    }

    protected virtual void Dispose( bool disposing )
    {
        if( _disposed )    
            return;

        if( disposing )
        {
            // Dispose managed resources here
        }

        _disposed = true;
    }
}
于 2008-09-17T21:43:02.550 に答える
1

プール内の各タイプのインスタンスの量を制限し、インスタンスで既に完了したものを再利用できます。プールのサイズは、処理するメッセージの量によって異なります。

于 2008-09-17T17:02:00.587 に答える
1

メッセージを受け取るたびにオブジェクトの新しいインスタンスを作成する代わりに、既に使用されているオブジェクトを再利用してみませんか? こうすれば、ガベージ コレクターと戦うことも、ヒープ メモリが断片化することもありません。**

メッセージの種類ごとに、使用されていないインスタンスを保持するプールを作成できます。ネットワーク メッセージを受信するたびに、メッセージの種類を確認し、待機中のインスタンスを適切なプールから取り出して、ビジネス ロジックを適用します。その後、メッセージ オブジェクトのインスタンスをそのプールに戻します。

コードを簡単にスケーリングできるように、プールにインスタンスを「遅延読み込み」することをお勧めします。したがって、プール クラスは、null インスタンスがプルされたことを検出し、渡す前にそれを埋める必要があります。次に、呼び出し元のコードがそれをプールに戻すと、それは実際のインスタンスになります。

** 「オブジェクト プーリングは、オブジェクトを割り当てたり割り当て解除したりするのではなく、再利用できるパターンです。これにより、ヒープの断片化やコストのかかる GC 圧縮を防ぐことができます。」

http://geekswithblogs.net/robp/archive/2008/08/07/speedy-c-part-2-optimizing-memory-allocations---pooling-and.aspx

于 2008-09-17T17:15:49.243 に答える
0

理論的には、CPU の負荷が高い場合、または本当に必要でない限り、GC は実行されるべきではありません。ただし、必要に応じて、すべてのオブジェクト (おそらくシングルトン インスタンス) をメモリ内に保持し、準備が整わない限りクリーンアップしないことをお勧めします。これが、GC がいつ実行されるかを保証する唯一の方法です。

于 2008-09-17T17:06:10.420 に答える