9

私が持っているいくつかの非同期TCPサーバーコードでは、プロセスがシステムのメモリ全体を消費する原因となるエラーが発生することがあります。ログ、イベントビューア、および一部のMSドキュメントを見ると、「呼び出し元のアプリケーションが同じクライアントに対して非同期IO呼び出しを複数回行うと、リモートクライアントがIの終わりを停止すると、ヒープの断片化とプライベートバイトの増加が見られる場合があります。 / O "。これにより、メモリ使用量が急増し、System.Threading.OverlappedData構造体とバイト配列が固定されます。

KBの記事で提案されている解決策は、「非同期IOで未処理の(送信または受信の)バッファーの量に上限を設定する」ことです。

どのようにこれを行うのですか?これは、BeginReadに送信されるbyte []を参照していますか?では、ソリューションは単にアクセスバイト[]をセマフォでラップするだけですか?

編集:バイトバッファへのセマフォ制御アクセス、またはバイトバッファの静的サイズのプールを持つことは2つの一般的な解決策です。セマフォまたはバイトバッファプールがあると、この非同期クライアントの問題が発生したときに(実際には奇妙なネットワークイベントである可能性があります)、メモリが不足するのを防ぐことができますが、問題は解決しません。私のバッファのプールは、問題のあるクライアントによって飲み込まれ、事実上、正しい機能の正当なクライアントをロックアウトする可能性があります。

編集2:この素晴らしい答えに出くわしました。基本的に、オブジェクトの固定を手動で解除する方法を示しています。非同期TCPコードは、実行時ルールの舞台裏にピン留めを残しますが、使用前に各バッファーを明示的にピン留めし、ブロックの最後または最後にピン留めを解除することで、これをオーバーライドできる場合があります。私は今それを理解しようとしています...

4

1 に答える 1

4

この問題に対処する1つの方法は、非同期通信で使用されるバッファーやその他のデータ構造を事前に割り当てることです。起動時に事前に割り当てると、メモリはヒープの同じ領域に自然に存在するため、断片化は発生しません。

.Net 3.5SP1に追加されたReceiveAsync/ APIを使用することをお勧めします。これにより、メモリバッファーのキャッシュまたは事前割り当てのみを許可する古い/ APIとは異なり、プロパティに格納された構造とメモリバッファーの両方をキャッシュまたは事前割り当てできます。SendAsyncSocketAsyncEventArgsSocketAsyncEventArgs.BufferBeginXXXEndXXX

APIが内部でWindowsオーバーラップI/O構造を何度も作成したため、古いAPIを使用するとCPUコストも大幅に増加しました。新しいAPIでは、これは内SocketAsyncEventArgsで行われるため、これらのオブジェクトをプールすることにより、CPUコストは1回だけ支払われます。

ピン留めに関する最新情報について:ピン留めには理由があります。つまり、デフラグ中にGCがバッファを移動しないようにするためです。手動で固定を解除すると、メモリが破損する可能性があります。

于 2012-05-28T20:40:39.910 に答える