大量の MSMQ キュー (現時点では約 10000) から読み取るアプリケーションがあります。queue.BeginPeek
UInt32.MaxValue タイムアウトを使用して、キューからメッセージを受信します。メッセージがキューに表示されたら、それを処理してqueue.BeginPeek
再度呼び出します。そのため、すべてのキューをリッスンしますが、メッセージ処理はスレッド プールで行われます。
メモリ使用量がゆっくりと増加していることに気付きました (2 週間の作業で 200 MB から 800 MB に増加します)。ダンプ ファイルを調べたところ、多くのフリー オブジェクトが含まれる典型的なヒープ フラグメンテーションの図が表示されます (サイズが数メガバイトのものもあります)。そして、穴の間にピンで留められたオブジェクトがあります。
これは、固定されたオブジェクトを作成するアンマネージ コードの呼び出しを操作する場合によくある状況のようです。しかし、私はインターネットで解決策を見つけられませんでした。
では、.NET のメモリ管理は非常に純粋なため、そのような単純なシナリオでさえ完了できないのでしょうか。
編集:サンプルアプリケーションでいくつかの調査を行いました。固定されたオブジェクト間のホール (フリー メモリ ゾーン、いわゆるフリー オブジェクト) は、新しいオブジェクトにメモリを割り当てるときに GC によって再利用されます。しかし、私の実稼働アプリケーションでは、固定されたオブジェクトは長生きし、最終的にそれらの間に穴が開いた第 2 世代で表示されます (GC は世代を分離する境界を移動するため)。通常の寿命の長いオブジェクトがほとんどないため、第 2 世代のダンプ ファイルにこの穴が見られます。
そのため、アプリケーションのメモリ消費量は 10000* (穴の平均サイズ) まで増加する可能性があります。(10000 は、将来的に増加する可能性のあるキューの数です)。現時点では、これを修正する方法がわかりません。唯一の方法は、時々アプリケーションを再起動することです。
繰り返しになりますが、なぜ .NET にはピン留めされたオブジェクト用の個別のヒープがないのでしょうか? (たぶんこれは初心者の質問です)。現時点では、アンマネージ コードで動作する非同期操作を呼び出すと、メモリの問題が発生する可能性があることがわかります。