• C和C++中的计时器


      在我们调试代码的时候,很多时候需要用代码的运行时间来衡量代码的效率,看了网上已经有了很多关于计时的文章,自己学习的时候再进行一些整理吧。

    1. time()函数 

      在头文件time.h中,time()获取当前的系统时间,只能精确到秒,返回的结果是一个time_t类型,其使用方法如下:

    #include <time.h>   
    #include <stdio.h>   
    
    int main() {  
         time_t first, second;  
         first=time(NULL);  
         delay(2000);  
         second=time(NULL);  
         printf("The difference is: %f seconds",difftime(second,first));  //调用difftime求出时间差
         return 0;   
    }   

     2. clock()函数

      在头文件time.h中,clock()函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock),常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元,精确到毫秒,其使用方法如下:

    #include<time.h>
    #include<stdio.h>
    
    int main()
    {
        double dur;
        clock_t start,end;
        start = clock();
        foo();//dosomething
        end = clock();
        dur = (double)(end - start);
        printf("Use Time:%f
    ",(dur/CLOCKS_PER_SEC));
    }

     

    3.timeGetTime()函数(Windows API

      以毫秒计的系统时间,该时间为从系统开启算起所经过的时间。在使用timeGetTime之前应先包含头文件#include <Mmsystem.h>或#include <Windows.h>并在project->settings->link->Object/library modules中添加winmm.lib。也可以在文件头部添加 #pragma comment( lib,"winmm.lib" )。

    备注:命令行:#pragma comment( lib,"xxx.lib" )时预编译处理指令,让vc将winmm.lib添加到工程中去进行编译。

    #include<stdio.h>
    #include<windows.h>
    
    #pragma comment( lib,"winmm.lib" )
    
    int main()
    {
        DWORD t1, t2;
        t1 = timeGetTime();
        foo();//do something
        t2 = timeGetTime();
        printf("Use Time:%f
    ", (t2 - t1)*1.0 / 1000);
        return 0;
    }

       该函数的时间精度是五毫秒或更大一些,这取决于机器的性能。可用timeBeginPeriod和timeEndPeriod函数提高timeGetTime函数的精度。如果使用了,连续调用timeGetTime函数,一系列返回值的差异由timeBeginPeriod和timeEndPeriod决定。也可以用timeGetTime实现延时功能Delay

    void Delay(DWORD delayTime)
    {
      DWORD delayTimeBegin;
      DWORD delayTimeEnd;
      delayTimeBegin=timeGetTime();
      do
      {
        delayTimeEnd
    =timeGetTime();
      }
    while((delayTimeEnd-delayTimeBegin)<delayTime) }
    
    
    

    4.QueryPerformanceCounter()函数和QueryPerformanceFrequency()函数(Windows API)

      QueryPerformanceFrequency()函数返回高精确度性能计数器的值,它可以以微妙为单位计时,但是QueryPerformanceCounter()确切的精确计时的最小单位是与系统有关的,所以,必须要查询系统以得到QueryPerformanceCounter()返回的嘀哒声的频率。QueryPerformanceFrequency()提供了这个频率值,返回每秒嘀哒声的个数。

    #include<stdio.h>
    #include<windows.h>
    #pragma comment( lib,"winmm.lib" )
    
    int main()
    {
        LARGE_INTEGER t1, t2, tc;
        QueryPerformanceFrequency(&tc);
        QueryPerformanceCounter(&t1);
        foo();//do something
        QueryPerformanceCounter(&t2);
        printf("Use Time:%f
    ", (t2.QuadPart - t1.QuadPart)*1.0 / tc.QuadPart);
        return 0;
    }

    5.GetTickCount()函数(Windows API)

      GetTickCount返回(retrieve)从操作系统启动所经过(elapsed)的毫秒数,它的返回值是DWORD。

    #include<stdio.h>
    #include<windows.h>
    #pragma comment( lib,"winmm.lib" )
    
    int main()
    {
        DWORD t1, t2;
        t1 = GetTickCount();
        foo;//do something
        t2 = GetTickCount();
        printf("Use Time:%f
    ", (t2 - t1)*1.0 / 1000);
        return 0;
    }

    6.RDTSC指令(Windows)

      在Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述几种方法所无法比拟的.在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31。

    inline unsigned __int64 GetCycleCount()
    {
        __asm
        {
            _emit 0x0F;
            _emit 0x31;
        }
    }
    
    void test6()
    {
        unsigned long t1,t2;
        t1 = (unsigned long)GetCycleCount();
        foo();//dosomething
        t2 = (unsigned long)GetCycleCount();
        printf("Use Time:%f
    ",(t2 - t1)*1.0/FREQUENCY);   //FREQUENCY指CPU的频率
    }

    获取CPU频率参考:http://blog.csdn.net/kofandlizi/article/details/6253801

    7.gettimeofday() (Linux)

    //timeval结构定义为:
    struct timeval
    {   
    long tv_sec; /**/   long tv_usec; /*微秒*/ };
    //timezone 结构定义为: struct timezone
    {   
    int tz_minuteswest; /*和Greenwich 时间差了多少分钟*/   int tz_dsttime; /*日光节约时间的状态*/ };
    void test() { struct timeval t1,t2; double timeuse; gettimeofday(&t1,NULL); foo(); gettimeofday(&t2,NULL); timeuse = t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec)/1000000.0; printf("Use Time:%f ",timeuse); }

     

    8.RDTSC指令计时(Linux)

    #if defined (__i386__)
    static __inline__ unsigned long long GetCycleCount(void)
    {
            unsigned long long int x;
            __asm__ volatile("rdtsc":"=A"(x));
            return x;
    }
    #elif defined (__x86_64__)
    static __inline__ unsigned long long GetCycleCount(void)
    {
            unsigned hi,lo;
            __asm__ volatile("rdtsc":"=a"(lo),"=d"(hi));
            return ((unsigned long long)lo)|(((unsigned long long)hi)<<32);
    }
    #endif
    
    void test8()
    {
            unsigned long t1,t2;
            t1 = (unsigned long)GetCycleCount();
            foo();//dosomething
            t2 = (unsigned long)GetCycleCount();
            printf("Use Time:%f
    ",(t2 - t1)*1.0/FREQUENCY); //FREQUENCY  CPU的频率
    }

    9.GetSystemTime / GetLocalTime(Windows)

      Windows SDK 中有两个精确到毫秒的获取当前时间的函数:

        GetSystemTime:获取 UTC 时间。

        GetLocalTime:获取当地时间。

      这两个函数的返回都是:SYSTEMTIME ,结构体占用了 16 个字节,它的定义如下:

    typedef struct _SYSTEMTIME {
      WORD wYear;
      WORD wMonth;
      WORD wDayOfWeek;
      WORD wDay;
      WORD wHour;
      WORD wMinute;
      WORD wSecond;
      WORD wMilliseconds;
    } SYSTEMTIME, *PSYSTEMTIME;
    // GetSystemTime.cpp : Defines the entry point for the console application.
    #include "stdafx.h"
    #include <Windows.h>
    
    int _tmain(void)
    {
        SYSTEMTIME utc_time = { 0 };
        SYSTEMTIME local_time = { 0 };
    
        GetSystemTime(&utc_time);
        GetLocalTime(&local_time);
        _tprintf(_T("The UTC time is 	: %02d:%02d:%02d.%03d
    "), utc_time.wHour, utc_time.wMinute, utc_time.wSecond, utc_time.wMilliseconds);
        _tprintf(_T("The local time is	: %02d:%02d:%02d.%03d
    "), local_time.wHour, local_time.wMinute, local_time.wSecond, local_time.wMilliseconds);
        return 0;
    }
    
    

    10.GetSystemTimeAsFileTime

      究竟能不能达到 100 纳秒的精确度呢?在 Windows SDK 中有一个结构体:FILETIME,它可以记录精度达到 100ns 的时间。用哪个函数得到这个值呢?可以用 GetSystemTimeAsFileTime。但是,不要高兴得太早,虽

    然 FILETIME 能够达到如此高的精度,但是这个函数我连试都懒得试。为什么呢?因为 Windows 系统并不是一个实时操作系统(Windows Embedded Compact 2013 是一个实时系统),其时钟精度一般认为是 15 ~ 16 毫秒。

    Windows Sysinternals 给我们提供了一个查看你使用的 Windows 系统的时钟分辨率的小工具:ClockRes v2.0。把它下载下来在控制台中执行,结果如下: 

    这里写图片描述

    看到了吧。死心了吧。所以说,用 GetSystemTime / GetLocalTime 就已经很好了。如果要获得真正毫秒级甚至更高精度的当前系统时间,必须跟 CPU 打交道,别无它法。先贴出代码吧:

    #ifdef _WIN32
    #include <windows.h>
    #else
    #include <time.h>
    #endif  // _WIND32
    
    
    // 定义64位整形
    #if defined(_WIN32) && !defined(CYGWIN)
    typedef __int64 int64_t;
    #else
    typedef long long int64t;
    #endif  // _WIN32
    
    // 获取系统的当前时间,单位微秒(us)
    int64_t GetSysTimeMicros()
    {
    #ifdef _WIN32
    // 从1601年1月1日0:0:0:000到1970年1月1日0:0:0:000的时间(单位100ns)
    #define EPOCHFILETIME   (116444736000000000UL)
        FILETIME ft;
        LARGE_INTEGER li;
        int64_t tt = 0;
        GetSystemTimeAsFileTime(&ft);
        li.LowPart = ft.dwLowDateTime;
        li.HighPart = ft.dwHighDateTime;
        // 从1970年1月1日0:0:0:000到现在的微秒数(UTC时间)
        tt = (li.QuadPart - EPOCHFILETIME) /10;
        return tt;
    #else
        timeval tv;
        gettimeofday(&tv, 0);
        return (int64_t)tv.tv_sec * 1000000 + (int64_t)tv.tv_usec;
    #endif // _WIN32
        return 0;
    }

    参考资料:http://blog.csdn.net/luoweifu/article/details/51325432

    http://blog.csdn.net/yapingxin/article/details/49466223

    http://www.cnblogs.com/leven20061001/archive/2012/11/08/2760126.html

  • 相关阅读:
    NVIC
    ONE WIRE
    对话框
    STM32_USART
    [Java]eclipse的使用
    [转] Android资源管理框架(Asset Manager)简要介绍和学习计划
    [其他]网站收录
    [Java]Java简介
    [网络技术]网关 路由器 OSI
    [安卓]安卓模拟器(Android Emulator)
  • 原文地址:https://www.cnblogs.com/chmm/p/7461684.html
Copyright © 2020-2023  润新知