この問題についてはかなりの数の議論がありましたが、彼らは私の特定の問題を説明できないようです。Threadクラスの代わりにThreadPoolを使用してスレッド化すると、パフォーマンスに深刻な問題が発生します。
詳細:
私はtcpサーバーを構築しました。tcpサーバーが新しいクライアントを受け入れると、そのクライアントを処理するための新しいスレッドが生成されます。すべてかなり単純ですが、サーバーが多くの同時クライアントを処理するには時間がかかりすぎます。2048バイトのバッファを送信して受信して閉じるだけの約35の単純なクライアントの場合は30秒。
ThreadPool.QueueUserWorkItem
何度もストップワスをした後、最大26秒かかることがわかりました。新しいクライアントを処理するための新しいスレッドを生成するために使用します。交換後ThreadPool.QueueUserWorkItem
、new Thread()
パフォーマンスは1秒未満に向上しました。
なぜこれが起こっているのかについての説明が欲しいです。
明確化:
ThreadPool.QueueUserWorkItemが呼び出されてからclientMsgHandler.HandleIncomingMsgsが開始されるまで、遅延はクライアントコードとは関係ありません。20秒が経過する可能性があります。
ラグは最初のスレッドから始まり、テストが続くにつれて実際にはわずかに改善されます。私は解決策にはあまり興味がなく、なぜそれが起こっているのかについての説明にもっと興味があります。クライアントはブロックしますが、非常に短い間です。
サーバーコード:
private void AddTcpClientMsgHandler(TcpClient tcpClient)
{
//lock so no addition of client and closure can occur concurrently
Stopwatch watch = new Stopwatch();
watch.Start();
Monitor.Enter(this);
int pWatchIdx = watchIDX++;
if (!isOpen)
throw new ObjectDisposedException(ResourceAlreadyClosed);
TcpClientMsgHandler clientMsgHandler = CreateClientHandler(tcpClient);
clientMsgHandlerManager.AddTcpClientMsgHandler(clientMsgHandler);
//ThreadPool.QueueUserWorkItem(clientMsgHandler.HandleIncomingMsgs); takes 20 seconds to run
Thread thread = new Thread(clientMsgHandler.HandleIncomingMsgs);
thread.Start();
watch.Stop();
Monitor.Exit(this);
Console.WriteLine(string.Format("Iteration {0} took {1} Client {2}", pWatchIdx.ToString(),watch.Elapsed, tcpClient.Client.RemoteEndPoint));
}