精确测量线程(C#)中代码的执行时间 [英] Precisely measure execution time of code in thread (C#)

查看:866
本文介绍了精确测量线程(C#)中代码的执行时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试尽可能精确地测量一些线程上一些代码的执行时间,同时考虑到上下文切换和线程停机时间.该应用程序是用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 之间的持续时间包括该线程实际上未运行的时间-它正在等待其他线程执行时再次进行调度.但是,滴答声计数仍会增加,因此持续时间现在确实是

代码块时间= A + B + 在其他线程中花费的时间

我只希望它

代码块时间= A + B

尤其是在线程数量较多的情况下,因为它们都将有机会运行,因此,在所有其他线程都在有问题的机会再获得运行之前,所有其他线程都将运行,因此上述计时会更高. /p>

所以我的问题是:是否可以某种方式计算线程运行的时间,然后相应地调整上述时间?我想完全(或至少)消除(减去)第三个术语.该代码运行了数百万次,因此最终时序是通过大量样本计算得出的,然后取平均值.

我不是在寻找探查器产品等-应用程序需要尽可能准确地计时这些标记的零件.功能 A B 是第三方功能,我无法对其进行任何更改.我还知道以纳秒精度测量时间时可能出现的波动以及这些第三方函数内部的可能开销,但是我仍然需要进行此测量.

任何建议将不胜感激-C ++或x86汇编代码也可以使用.

似乎无法实现. Scott下面的想法(使用GetThreadTimes)是好的,但是不幸的是,GetThreadTimes()是一个有缺陷的API,它几乎从不返回正确的数据.感谢您的所有答复!

解决方案

可以通过本机API调用关于CodeProject的文章.

第二种选择是使用 QueryThreadCycleTime .这不会给您时间,但是会给您当前线程已执行的周期数.

请注意,由于许多处理器(尤其是移动处理器)不是以固定速度运行,因此您不能直接将其转换为cycles->seconds,因此没有常数可以乘以获取秒.但是,如果您使用的处理器不会改变其速度,那么从周期中获取挂钟时间将是一个简单的数学问题.

I'm trying to measure the execution time of some bits of code as accurately as possible on a number of threads, taking context switching and thread downtime into account. The application is implemented in C# (VS 2008). Example:

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 );
}

I'd like to measure the execution time of the above two critical code blocks as accurately as possible. The two calls marked as A and B are potentially long function calls that may sometimes take several seconds to execute but in some cases they may complete in a few milliseconds.

I'm running the above code on a number of threads - somewhere between 1 to 200 threads, depending on user input. The computers running this code have 2-16 cores - users use lower thread counts on the weaker machines.

The problem is that A and B are both potenitally long functions so it's very likely that at least one context switch will happen during their execution - possibly more than one. So the code gets lTimestamp1, then another thread starts executing (and the current thread waits). Eventually the current thread gets back control and retrieves lTimestamp2.

This means that the duration between lTimestamp1 and lTimestamp2 includes time when the thread was not actually running - it was waiting to be scheduled again while other threads executed. The tick count, however, increases anyway, so the duration is now really

Code block time = A + B + some time spent in other threads

while I want it to be only

Code block time = A + B

This is especially an issue with a larger number of threads, since they'll all get a chance to run, so the above timings will be higher while all other threads run before the thread in question gets another chance to run.

So my question is: is it possible to somehow calculate the time when the thread is not running and then adjust the above timings accordingly? I'd like to eliminate (subtract) that 3rd term entirely or at least as much of it as possible. The code runs millions of times, so final timings are calculated from a lot of samples and then averaged out.

I'm not looking for profiler products, etc. - the application needs to time these the marked parts as accurately as possible. The functions A and B are 3rd party functions, I cannot change them in any way. I'm also aware of the possible fluctuations when measuring time with nanosecond precision and possible overhead inside those 3rd-party functions, but I still need to do this measurement.

Any advice would be greatly appreciated - C++ or x86 assembly code would work as well.

Edit: seems to be impossible to implement this. Scott's idea below (using GetThreadTimes) is good but unfortunately GetThreadTimes() is a flawed API and it almost never returns correct data. Thanks for all the replies!

解决方案

This can be done with the Native API call GetThreadTimes. Here is a article on CodeProject that uses it.

A second option is use QueryThreadCycleTime. This will not give you the time, but it will give you the number of cycles the current thread has been executing.

Be aware you can't just directly convert cycles->seconds due to the fact that many processors (especially mobile processors) do not run at a fixed speed so there is no constant number you could multiply by to get the elapsed time in seconds. But if you are using a processor that does not vary its speed it then would be a simple math problem to get wall clock time from the cycles.

这篇关于精确测量线程(C#)中代码的执行时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆