对老赵写的简单性能计数器的修改续- 关于 GetThreadTimes

本文探讨了GetThreadTimes API在获取线程实际运行时间时的不准确性。通过示例代码和分析,揭示了该API由于依赖时间中断更新计数导致的误差,并对比了实际CPU使用时间和测量结果。实验结果显示,线程长时间连续占用CPU或恰好连续占用时间片的情况下,GetThreadTimes的统计才可能接近准确,但在大多数情况下,其得到的线程占用时间是不准确的。
摘要由CSDN通过智能技术生成

关于 GetThreadTimes

    我在一篇博文中 《对老赵写的简单性能计数器的修改 》  提到用 GetThreadTimes 这个Win32 API 来获取线程实际运行时间。今天我又深入研究了一下,发现这个API 返回的时间并不准确。

    首先我们先看一下 GetThreadTimes 的实现原理:

    在 kernel32.dll 内部 GetThreadTimes 首先调用 NtQueryInformationThread 获取线程TCB信息,然后从TCB 中获取线程的内核态计数和用户态计数。然而这个计数值并不是实时增加的,操作系统只是在时间中断(10/15ms一次,单处理器通常是10ms,多处理器 15ms)发生时增加当前线程的计数。这里就出现一个问题,如果时间中断发生时,被统计线程恰好不在活动状态,即不是当前线程,那么这个线程就不会增加计 数。所以只有线程长时间连续占用CPU,或者每次都正好连续占用一个完整的时间片(10/15ms一次),才能确保这个线程的统计结果是准确的。但实际情 况是,线程不可能连续占用CPU(否则其他程序就别玩了,如果你一定要这样我也没办法),也不可能每次都恰巧占用完整的时间片(线程工作过程中往往会需要 Sleep,或者阻塞等待资源或者被高优先级线程打断)。所以显而易见,这个计数是不精确的。

    下面给出我写的一个示例代码。

    这个代码在我机器上运行,如果将Thread.Sleep(1); 这行注释掉,显示耗时是140毫秒,但如果不注释这行,显示耗时是0毫秒。

    原因就是我们将140毫秒的时间强行分成了1000个很小的时间,每次线程只消耗大约0.14 毫秒的CPU时间,而在这1秒左右的时间(约 1000*1ms+140ms)

 时间里,共发生1140 / 15 = 74 次时间中断(我的机器是双核的),每次中断时,主线程正好在运行的概率不高,如果这74次中断中没有一次击中当前线程,

 则当前线程的计数增长始终为0。

 

       
        [DllImport(
" kernel32.dll " , SetLastError  =   true )]
        
static   extern   bool  GetThreadTimes(IntPtr hThread,  out   long  lpCreationTime,
           
out   long  lpExitTime,  out   long  lpKernelTime,  out   long  lpUserTime);

        [DllImport(
" kernel32.dll " )]
        
static   extern  IntPtr GetCurrentThread();

        
private   static   long  GetCurrentThreadTimes()
        
{
            
long  l;
            
long  kernelTime, userTimer;
            GetThreadTimes(GetCurrentThread(), 
out  l,  out  l,  out  kernelTime,  out  
               userTimer);
            
return  kernelTime  +  userTimer;
        }


        
static   void  TestGetThreadTimes()
        
{
            
long  lst  =  GetCurrentThreadTimes();
            
string  a  =   "" ;

            
for  ( int  i  =   0 ; i  <   10000 ; i ++ )
            
{
                a 
+=   " a " ;

                
if  (i  %   10   ==   0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值