コンテキストの切り替えとスレッドのダウンタイムを考慮して、いくつかのコードの実行時間を多くのスレッドで可能な限り正確に測定しようとしています。アプリケーションは C# (VS 2008) で実装されています。例:
public void ThreadFunc ()
{
// Some code here
// Critical block #1 begins here
long lTimestamp1 = Stopwatch.GetTimestamp ();
CallComplex3rdPartyFunc (); // A
long lTimestamp2 = Stopwatch.GetTimestamp ();
// Critical block #1 ends here
// Some code here
// Critical block #2 begins here
long lTimestamp3 = Stopwatch.GetTimestamp ();
CallOtherComplex3rdPartyFunc (); // B
long lTimestamp4 = Stopwatch.GetTimestamp ();
// Critical block #2 ends here
// Save timestamps for future analysis.
}
public int Main ( string[] sArgs )
{
// Some code here
int nCount = SomeFunc ();
for ( int i = 0; i < nCount; i++ )
{
Thread oThread = new Thread ( ThreadFunc );
oThread.Start ();
}
// Some code here
return ( 0 );
}
上記の 2 つの重要なコード ブロックの実行時間をできるだけ正確に測定したいと考えています。AおよびBとしてマークされた 2 つの呼び出しは、潜在的に長い関数呼び出しであり、実行に数秒かかる場合もありますが、場合によっては数ミリ秒で完了する場合もあります。
上記のコードを多数のスレッドで実行しています - ユーザーの入力に応じて、1 から 200 スレッドの間のどこかです。このコードを実行するコンピューターには 2 ~ 16 のコアがあり、ユーザーはより弱いマシンでより低いスレッド数を使用します。
問題は、AとBの両方が潜在的に長い関数であるため、実行中に少なくとも 1 回のコンテキスト スイッチが発生する可能性が非常に高く、おそらく複数回発生することです。そのため、コードが lTimestamp1 を取得すると、別のスレッドが実行を開始します (現在のスレッドは待機します)。最終的に、現在のスレッドが制御を取り戻し、lTimestamp2 を取得します。
これは、lTimestamp1とlTimestamp2の間の期間には、スレッドが実際に実行されていなかった時間 (他のスレッドが実行されている間、スレッドが再度スケジュールされるのを待っていた時間) が含まれていることを意味します。ただし、ティック数はとにかく増加するため、期間は実際には
コード ブロック時間 = A + B +他のスレッドで費やされた時間
それだけでありたいと思っている間
コードブロック時間 = A + B
これは、多数のスレッドで特に問題になります。すべてのスレッドが実行される可能性があるため、問題のスレッドが実行される別の機会が得られる前に他のすべてのスレッドが実行される間、上記のタイミングが高くなります。
私の質問は次のとおりです。スレッドが実行されていない時間を何らかの方法で計算し、それに応じて上記のタイミングを調整することは可能ですか? その第 3 項を完全に、または少なくとも可能な限り削除 (減算) したいと思います。コードは何百万回も実行されるため、最終的なタイミングは多くのサンプルから計算され、平均化されます。
プロファイラー製品などを探しているわけではありません。アプリケーションは、これらのマークされたパーツの時間をできるだけ正確に計る必要があります。関数AとBはサード パーティの関数であり、どのような方法でも変更できません。また、ナノ秒の精度で時間を測定するときに変動する可能性と、これらのサードパーティ関数内でオーバーヘッドが発生する可能性があることも認識していますが、それでもこの測定を行う必要があります。
C++ または x86 アセンブリ コードも同様に機能します。
編集:これを実装することは不可能のようです。以下の Scott のアイデア (GetThreadTimes を使用) は優れていますが、残念ながら GetThreadTimes() には欠陥のある API があり、正しいデータを返すことはほとんどありません。すべての返信に感謝します!