2012-05-21 5 views
8

私はいくつかの非同期tcpサーバーコードで、システム全体のメモリを消費するエラーが発生することがあります。ログ、イベントビューア、およびいくつかの "MS docs"を見ると、 "呼び出し元のアプリケーションが同じクライアントに複数の非同期IOコールを複数回送信すると、リモートクライアントがI/Oの終了を停止するとヒープフラグメンテーションとプライベートバイトが増加することがあります。 O "を使用すると、System.Threading.OverlappedData構造体とバイト配列のメモリ使用量と固定量が増加します。非同期tcp .NETコードがシステムリソース全体を使い果たしてしまうのを防ぐ方法

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

どうすればよいですか?これはBeginReadに送られるbyte []を参照していますか?だから、解決策は単にセマフォを使ってアクセスバイト[]をラップしますか?

EDIT:バイトバッファへのセマフォ制御のアクセス、または静的なサイズのバイトバッファプールの2つの共通の解決策があります。私がまだ残っている懸念は、この非同期クライアントの問題が発生したとき(セマンフォーまたはバイトバッファープールを持つことによって実際には変わったネットワークイベントが発生する)、メモリが不足するのを防ぐことができますが、問題は解決しないということです。バッファーの私のプールは、問題のクライアントが実際に正当な機能を持つクライアントをロックしてしまう可能性があります。

編集2:この偉大な間に来たanswer。基本的には、手動でオブジェクトを固定解除する方法を示しています。また、非同期TCPコードはシーンランタイムルールの背後に固定されていますが、使用する前に明示的に各バッファを固定し、ブロックの最後または最後に固定解除することでオーバーライドできます。私は今それを理解しようとしています...

+0

可能な複製:http://stackoverflow.com/questions/236171/net-does-not-have-reliable-asynchronouos-socket-communication – Dennis

+0

これはセマフォを使用してBeginReadへの呼び出しをラップする方法です。 – mikalai

+0

これはコードをプロファイリングするのに十分な理由かもしれません... – gsscoder

答えて

3

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

私はAPIは、.NET 3.5のみ許可 BeginXXX/ EndXXX古いAPIのとは異なり、あなたは SocketAsyncEventArgs構造と SocketAsyncEventArgs.Bufferプロパティに格納されたメモリバッファの両方をキャッシュするか、事前に割り当てることができますSP1、に加え、 ReceiveAsync/ SendAsyncを使用することをお勧めし

メモリバッファのキャッシングまたは事前割り当てを行う。

APIは内部的にWindowsオーバーラップI/O構造を繰り返し作成していたため、古いAPIを使用すると相当なCPUコストが発生しました。新しいAPIではSocketAsyncEventArgsの範囲内で行われるため、これらのオブジェクトをプールすることでCPUコストは1回のみ支払われます。

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

関連する問題