我正尝试在多个线程上尽可能准确地测量一些代码片段的执行时间,考虑到上下文切换和线程停机时间。该应用程序是使用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 );
}
我想尽可能准确地测量以上两个关键代码块的执行时间。标记为A和B的两个调用是潜在的长函数调用,有时可能需要几秒钟才能执行,但在某些情况下,它们可能只需几毫秒就能完成。我在许多线程上运行上述代码 - 1到200个线程之间,具体取决于用户输入。运行此代码的计算机具有2-16个核心 - 用户在较弱的机器上使用较低的线程计数。
问题在于A和B都是潜在的长函数,因此在其执行期间很可能会发生至少一个上下文切换 - 可能不止一个。因此,代码获取lTimestamp1,然后另一个线程开始执行(当前线程等待)。最终,当前线程重新获得控制并检索lTimestamp2。
这意味着lTimestamp1和lTimestamp2之间的持续时间包括线程实际上没有运行的时间 - 它正在等待再次调度,而其他线程在执行。然而,滴答数仍然增加,因此持续时间现在实际上是
Code block time = A + B + some time spent in other threads 而我希望它仅为
Code block time = A + B
这在更多线程的情况下尤其成问题,因为它们都有机会运行,所以上述时间将更长,而所有其他线程都在该线程再次获得运行机会之前运行。
那么我的问题是:是否可能以某种方式计算线程不运行的时间,然后相应地调整上述时间?我希望完全消除(减去)第三项,或者至少尽可能减少它。代码运行数百万次,因此最终时间是从大量样本计算并平均的。
我不需要关注剖析器产品等 - 应用程序需要尽可能准确地计时这些标记部分。函数A和B是第三方函数,我无法以任何方式更改它们。我也意识到,当使用纳秒精度测量时间并且3rd-party函数内部可能存在开销时,可能会出现波动,但我仍然需要进行此测量。
任何建议都将不胜感激- C++或x86汇编代码也可以。
编辑:似乎不可能实现这一点。Scott下面的想法(使用GetThreadTimes)很好,但不幸的是,GetThreadTimes()是一个有缺陷的API,它几乎永远不返回正确的数据。感谢所有答复!