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\n",(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\n", (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\n", (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\n", (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\n",(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\n",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\n",(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 \t: %02d:%02d:%02d.%03d\n"), utc_time.wHour, utc_time.wMinute, utc_time.wSecond, utc_time.wMilliseconds);
    _tprintf(_T("The local time is\t: %02d:%02d:%02d.%03d\n"), 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

时间: 2024-08-28 17:45:22

C和C++中的计时器的相关文章

C#中各种计时器 Stopwatch、TimeSpan

1.使用 Stopwatch 类 (System.Diagnostics.Stopwatch) Stopwatch 实例可以测量一个时间间隔的运行时间,也可以测量多个时间间隔的总运行时间.在典型的 Stopwatch 方案中,先调用 Start 方法,然后调用 Stop 方法,最后使用 Elapsed 属性检查运行时间. Stopwatch 实例或者在运行,或者已停止:使用 IsRunning 可以确定 Stopwatch 的当前状态.使用 Start 可以开始测量运行时间:使用 Stop 可以

JS中的计时器事件

JS可以实现很多java代码不易完成的功能.这里学习一些js中的计时器事件. JavaScript 一个设定的时间间隔之后来执行代码,称之为计时事件. 主要通过两个方法来实现: 1.setInterval() - 间隔指定的毫秒数不停地执行指定的代码. 2.setTimeout() - 暂停指定的毫秒数后执行指定的代码 并且,这两个方法都是window对象的方法. 首先,介绍setInterval()方法,该方法值得是间隔一定的毫秒数不停的执行指定的代码. 语法:window.setInterv

aspx利用cookie值来停止silverlight中的计时器

一.silverlight与silverlight中可以利用委托(delegate)来刷新frame.Refresh() 1.在子类中定义委托捕捉关闭事件按钮 1 public delegate void onCloseClick(object sender, RoutedEventArgs e); 2 public onCloseClick onclose; 3 private void CancelButton_Click(object sender, RoutedEventArgs e)

TCP协议中的计时器

说明:  本文仅供学习交流,转载请标明出处,欢迎转载! 本文是以下文献相关内容的总结 [1] <TCP/IP详解 卷1:协议> [2] <TCP/IP协议族 第4版> [3] <计算机网络 第5版> TCP协议通常包括4种计时器:重传计时器.持续计时器.保活计时器和时间等待计时器. 重传计时器:Retransmission Timer,该计时器用于整个连接期间,用于处理RTO(重传超时).当一个报文从发送队列发出去后,就启动该计时器.若在RTO之内收到了该报文的ACK,

TCP中的计时器

TCP中的计时器? (1)重传计时器 TCP发送完一个报文段,就设置一个专属于此报文段的计时器,规定时间内收到此报文段的确认,撤销计时器,时间走完还没收到确认包,重传此报文段并重置计时器. (2)持续计时器 客户端收到的确认包窗口是0,便停止发送数据了.过了一会,接收端缓过来劲了,继续发送一个更高序号的字节的确认包,它的窗口大于0,客户端如果收到此确认包,检测到窗口大于0,就会重新发送数据.但是如果此"激活"确认包万一丢失,双方都会永久静默下去(TCP不会重传ACK确认包).所以为每个

js中的计时器事件`setTimeout()` 和 `setInterval()`

js中的计时器事件 在js中,通常会有一些事件,我们需要让它 间隔一段时间之后再发生,或者 每隔一段时间 发生一次,那就需要用到我们js中的计时事件 计时事件主要有两种: setTimeout() ---- 间隔一定的时间之后执行 setInterval() ----每间隔一定的时间执行一次(重复性执行) setTimeout() 间隔一定的时间之后`执行指定的语句或函数. 例如:3s后跳转到前一个页面. <script type="text/javascript"> se

js中的计时器

在JS中做二级菜单时,被一个鼠标移出时隐藏的小问题困扰了很久. <script> function Menu(id){ var _this=this; this.obj=document.getElementById(id); this.trigger=getFirstChild(this.obj); this.menuOne=getLastChild(this.obj); this.menuOneLi=getChildren(this.menuOne); this.menuOneLiA=[]

JavaScript中的计时器原理及使用情况

理解John Resig 在 How JavaScript Timers Work. timer(setInterval,setTimeout)有一个很重要的概念,时间延迟的长短是不稳定的.因为所有的javascript都是在单一线程中执行,那些异步的事件(比如说鼠标点击,或者timer)只在执行期出现空闲的时候才会运行.下图能很好的说明这个情况. 此例中有三个异步事件,鼠标点击,setTimeout,setInterval. 先介绍一下这个图的构成,左侧以10为间隔的横杠是以ms为单位从上至下

2.6 内核中的计时器和列表【转】

转自:http://www.cnblogs.com/hoys/archive/2011/11/14/2248586.html 计时器是所有操作系统的一个必要组成部分,您将发现多个计时器机制.我们将首先简要介绍一些 Linux 计时器模式,然后深入研究它们的运行方式. (Linux)时间的起源 在 Linux 内核中,时间由一个名为 jiffies 的全局变量衡量,该变量标识系统启动以来经过的滴答数.在最低的级别上,计算滴答数的方式取决于正在运行的特定硬件平台:但是,滴答计数通常在一次中断期间仍然

C++ 中的计时器

在Java中,有时候会要测试程序的性能,所以会采用System.currentTimeMillis()等类库函数去测试时间开销. 在C++中同样可以完成此功能. 头文件: #include<ctime> 示例程序: 1 #include<iostream> 2 #include<ctime> 3 using namespace std; 4 const int N =10000000; 5 int main(){ 6 clock_t now = clock(); 7 f