(dotTrace を使用して) アプリケーションをプロファイルしているときに、非常に奇妙なことに気付きました。「壁時間」測定を使用しました。これは、理論的には、すべてのスレッドが同じ時間実行されることを意味するはずです。
しかし、これは真実ではありませんでした: 一部のスレッド (実際に私が最も興味を持っていたスレッド) は、他のスレッドの約 2 分の 1 の合計時間を表示しました。たとえば、プロファイリングは 230 秒間実行され、ほとんどのスレッドはスレッドで費やされた 230 秒を報告しますが、5 つのスレッドは 100 ~ 110 秒しか示しません。これらはスレッドプール スレッドではなく、プロファイリングが開始される前に確実に作成および開始されました。
ここで何が起こっているのですか?
更新関連する情報と関連しない情報を追加します。問題のアプリケーション (ゲーム サーバー) には、約 20 ~ 30 の常時実行中のスレッドがあります。ほとんどのスレッドは単純なパターンに従います。つまり、着信キューで作業をチェックし、作業があれば作業を行います。スレッド func のコードは次のようになります。
while(true){
if(TryDequeueWork()){ // if queue is not empty
DoWork(); // do whatever is was on top
}else{
m_WaitHandle.WaitOne(MaxTimeout); // m_WaitHandle gets signaled when work is added to queue
}
}
奇妙な時間を表示するスレッドは、次のように複数のキューを提供することを除いて、次のようになります。
while(true){
bool hasAnyWork=false;
foreach(var queue in m_Queues){
if(queue.TryDequeueWork()){
hasAnyWork=true;
DoWork();
}
}
if(!hasAnyWork){
m_WaitHandle.WaitOne(MaxTimeout);
}
}
奇妙なスレッドは、ロギング以外の IO を実行しません。他の、変ではないスレッドもロギングを行います。WaitHandle の待機に費やされた時間は、プロファイラーで報告されます。実際には、おかしくないスレッドの中には、ほとんどすべての時間を待機に費やしているものもあります (作業がないため)。
アプリケーションは、8 コアの仮想マシン (VPS ホスティング) で実行されていました。そこで使用されている物理プロセッサはわかりません。