IA32/Windows&Linux高精度计时器

IA32/Windows&Linux高精度计时器

System Clock级高精度计时器,支持Window/Linux平台。输入参数CPU主频,该值可从注册表(Windows)或/proc/cpuinfo(Linux)中获得。
大道至简——精度高,抖动大

//  *****************************************************************************
//   IA32Timer   version:  1.0    date: 04/26/2006
//   ----------------------------------------------------------------------------
//   This class is a wrapper of IA32 RDTSC 
//   (ReaD Time Stamp Counter) instruction.
//   It will help you get the interval time with
//   different level.
//   ----------------------------------------------------------------------------
//   Copyright (C) 2006 - Charles Zu
//  *****************************************************************************
//      Note: All the classes the author designed are leading with "Z"
//   which is contradistinguished form the leading with "C" of MFC
//  *****************************************************************************

class  ZIA32Timer
{
public :
    ZIA32Timer(
double  ghz)
    :m_startcycle(
0 ), m_ghz(ghz)
    
{
#ifndef _WIN32
        m_high 
=   0 ;
        m_low 
=   0 ;
#endif
    }


    
void  Start()
    
{
#ifdef _WIN32
        m_startcycle 
=  RTSC();
#else
        RTSC();
        m_startcycle 
=  (unsigned  long   long ) m_high  *  ( 1   <<   30 *   4   +  m_low;
#endif
    }


#ifdef _WIN32
    unsigned __int64 Stop(
int  unit);
#else
    unsigned 
long   long  Stop( int  unit);
#endif

    
static   enum  Unit {CYCLE, NS, US, MS, S} s_unit;

private :
#ifdef _WIN32
    unsigned __int64  m_startcycle;
#else
    unsigned 
long   long  m_startcycle;
    unsigned 
int  m_high;
    unsigned 
int  m_low;
#endif

#ifdef _WIN32
    unsigned __int64 RTSC();
#else
   
void  RTSC();
#endif

double  m_ghz;

}
;

#ifdef _WIN32
    inline unsigned __int64 ZIA32Timer::RTSC()
    
{
        _asm    _emit 
0x0F
        _asm    _emit 
0x31
    }

#else
    inline 
void  ZIA32Timer::RTSC()
    
{
        asm(
" rdtsc; movl %%edx,%0; movl %%eax,%1 "     //  Read cycle counter
            :  " =r "  (m_high),  " =r "  (m_low)                                    
            : 
/**/ /*  No input  */                              
            : 
" %edx " " %eax " );
    }

#endif

#ifdef _WIN32
    inline unsigned __int64 ZIA32Timer::Stop(
int  unit)
    
{
        
switch (unit)
        
{
        
case  CYCLE:
            
return  (unsigned __int64)(RTSC()  -  m_startcycle);
        
break ;

        
case  NS:
            
return  (unsigned __int64)((RTSC()  -  m_startcycle)  /  m_ghz);
        
break ;

        
case  US:
            
return  (unsigned __int64)((RTSC()  -  m_startcycle)  /  m_ghz  /   1000 );
        
break ;

        
case  MS:
            
return  (unsigned __int64)((RTSC()  -  m_startcycle)  /  m_ghz  /   1000000 );
        
break ;

        
case  S:
            
return  (unsigned __int64)((RTSC()  -  m_startcycle)  /  m_ghz  /   1000000000 );
        
break ;

        
default :
            
break ;
        }

        
return   0 ;
    }

#else
    inline unsigned 
long   long  ZIA32Timer::Stop( int  unit)
    
{
        unsigned 
long   long  stoppiont;
        RTSC();
        stoppiont 
=  (((unsigned  long   long )m_high)  <<   32 +  m_low;
        
        
switch (unit)
        
{
        
case  CYCLE:
            
return  (unsigned  long   long )(stoppiont  -  m_startcycle);
            
break ;

        
case  NS:
            
return  (unsigned  long   long )((stoppiont  -  m_startcycle)  /  m_ghz);
            
break ;

        
case  US:
            
return  (unsigned  long   long )((stoppiont  -  m_startcycle)  /  m_ghz  /   1000 );
            
break ;

        
case  MS:
            
return  (unsigned  long   long )((stoppiont  -  m_startcycle)  /  m_ghz  /   1000000 );
            
break ;

        
case  S:
            
return  (unsigned  long   long )((stoppiont  -  m_startcycle)  /  m_ghz  /   1000000000 );
            
break ;

        
default :
            
break ;
        }

        
return   0 ;
    }

#endif

下边给个测试程序,由于我的CPU主频为3GHZ,所以写了hard code
#include  < stdio.h >
#ifdef _WIN32
#include 
< windows.h >
#else
#include 
< unistd.h >
#endif

#include 
" IA32Timer.h "

void  MySleep()
{
#ifdef _WIN32
//     Sleep(1);
     Sleep(10);
//     Sleep(100);
//     Sleep(1000);
#else
    usleep(
100 * 1000);
#endif
}


int  main( int  argc,  char **  argv)
{
    ZIA32Timer ztimer(
3); //the arg is the GHZ of your CPU

#ifdef _WIN32
unsigned __int64 interval;
#else
unsigned 
long long interval;
#endif

    ztimer.Start();
    MySleep();
    interval 
= ztimer.Stop(ZIA32Timer::CYCLE);
    fprintf(stdout, 
"interval = %u (cycle)\n", interval);

    ztimer.Start();
    MySleep();
    interval 
= ztimer.Stop(ZIA32Timer::NS);
    fprintf(stdout, 
"interval = %u (ns)\n", interval);

    ztimer.Start();
    MySleep();
    interval 
= ztimer.Stop(ZIA32Timer::US);
    fprintf(stdout, 
"interval = %u (us)\n", interval);

    ztimer.Start();
    MySleep();
    interval 
= ztimer.Stop(ZIA32Timer::MS);
    fprintf(stdout, 
"interval = %u (ms)\n", interval);

    ztimer.Start();
    MySleep();
    interval 
= ztimer.Stop(ZIA32Timer::S);
    fprintf(stdout, 
"interval = %u (s)\n", interval);

    
return 0;
}

参考了高人的汇编实现,自己整理,贴出来,希望对你有启示

你可能感兴趣的:(IA32/Windows&Linux高精度计时器)