私はサーバーアプリケーションの書き直しを進めており、アプリケーションのメモリ使用量に困惑しています。以前のバージョンはTcpListener
と書かれましたが、新しいバージョンは普通の古いものですSocket
。これは主に、パフォーマンスと安定性の理由から、この問題やこの問題の副次的なものです。非同期ソケット高いメモリ使用率と可能なリーク
前述したように、すべては、AcceptAsync
,SendAsync
、およびReceiveAsync
と大きく非同期です。さらに、AcceptAsync
の最初のキックオフ、次のAcceptAsync
のキューイング、Socket
に書き戻すための処理後のコール、切断されたコールのクリーンアップなどのユーティリティタスクにはThreadPool.QueueUserWorkItem
を使用します。さらに、私はBeginInvoke
とEndInvoke
で発砲する一連のイベントがあります。
もの切断ならびにデータの可用性のためのメインドライバの検出はReceiveAsync
ならびにDisconnect
イベントを発生させ、ゼロであるSocketAsyncEventArgs.BytesTransferred
する検出上のピークIはAvailabilityNotifier
を呼び出すカスタムクラスによって処理されます。
アプリケーションのスループットは良好で、System.Collections.Concurrent
オブジェクトの健全な使用のおかげで、ほとんどゼロ(相対的に言えば)のロック競合があります。しかし、それは殺すために執着する捕食者のように記憶に固執する。
私は内部のコレクションがクリアされていることを確認するためにデバッグしました。クライアントソケットはシャットダウンされ、処分されており、読み込みごとに新しいバッファを作成する代わりにバッファプールを利用しています。最終的に1,000接続(100同時実行)と100,000メッセージの送受信を実行するテストアプリケーションを実行すると、サーバープロセスメモリが約800 MBに膨れ上がり、WindowsがTIME_WAIT
をクリアしてもダウンしません。私はdiposalコードがObjectDisposedException
のトンとヌル例外catch
のブロックのおかげで発火していることを知っています。ブロックは下のリンクされたgithubで見ることができます。
私は引用符なしですべてここに記事のためにかなり長いのでここにgithub:https://github.com/hoagsie/TcpServerだと言う。 Program.cs
とClientProgram.cs
は、自分で実行したい場合にも提供されますが、主な操作はNetworkServer.cs
とAvailabilityNotifier.cs
です。私が実行しているサンプルサーバーには、会話するWCFサービスがありますが、文字通り変更のない標準のWCFプロジェクトです。私はサンプルシナリオに合わせるためにそれを必要としました。
あるレベルで問題があるかどうかもわかりませんが、AnyCPU/x86ではなくx64モードでビルドします。これは主にターゲットサーバー上でのリソース消費機会のためですが、x86またはx64でこの問題に関する動作の違いに気づいていません。
EDIT:
同僚は、Visual Studioでスナップショットツールを指摘しました。私は以前これを見たことがなかったし、それは私が使っていたものとは異なったものを表示していた。これはdotTraceだった。それは意味を成すSocketAsyncEventArgs
オブジェクトの周りの割当量を指摘しましたが、彼らは建物と建物を維持しました。メンバーリストをもう一度見て、Dispose
メソッドがあることを発見しました。私の問題は消えてしまった。私はそれがIDisposable
オブジェクトであることに気付かなかった。