转自:http://blog.csdn.net/fz_ywj/article/details/8109368

C语言中常用计时方法总结

1. time()

头文件:time.h

函数原型:time_t time(time_t * timer)

功能:返回以格林尼治时间(GMT)为标准,从1970年1月1日00:00:00到现在的此时此刻所经过的秒数。

用time()函数结合其他函数(如:localtime、gmtime、asctime、ctime)可以获得当前系统时间或是标准时间。

用difftime函数可以计算两个time_t类型的时间的差值,可以用于计时。用difftime(t2,t1)要比t2-t1更准确,因为C标准中并没有规定time_t的单位一定是秒,而difftime会根据机器进行转换,更可靠。

用法

  1. time_t start,end;
  2. start =time(NULL);//or time(&start);
  3. //…calculating…
  4. end =time(NULL);
  5. printf("time=%d\n",difftime(end,start));

总结:C标准库中的函数,可移植性最好,性能也很稳定,但精度太低,只能精确到秒,对于一般的事件计时还算够用,而对运算时间的计时就明显不够用了。

2. clock()

头文件:time.h

函数原型:clock_t clock(void);

功能:该函数返回值是硬件滴答数,要换算成秒,需要除以CLK_TCK或者 CLK_TCKCLOCKS_PER_SEC。比如,在VC++6.0下,这两个量的值都是1000。

用法

  1. clock_t start,end;
  2. start = clock();
  3. //…calculating…
  4. end = clock();
  5. printf("time=%f\n",(double)end-start)/CLK_TCK);

总结:可以精确到毫秒,适合一般场合的使用。

3. timeGetTime()

WIN32API

头文件:Mmsystem.h  引用库: Winmm.lib

函数原型:DWORD timeGetTime(VOID);

功能:返回系统时间,以毫秒为单位。系统时间是从系统启动到调用函数时所经过的毫秒数。注意,这个值是32位的,会在0到2^32之间循环,约49.71天。

用法

  1. DWORDstart,end;
  2. start= timeGetTime();
  3. //…calculating…
  4. end= timeGetTime();
  5. printf("time=%d\n",end-start);

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

4. GetTickCount()

WIN32API

头文件:windows.h

函数原型:DWORD WINAPI GetTickCount(void);

功能:返回自设备启动后的毫秒数(不含系统暂停时间)。

用法

  1. DWORDstart,end;
  2. start= GetTickCount();
  3. //…calculating…
  4. end= GetTickCount();
  5. printf("time=%d\n",end-start);

总结:精确到毫秒。对于一般的实时控制,使用GetTickCount()函数就可以满足精度要求。

5. QueryPerformanceCounter()、QueryPerformanceFrequency()

WIN32API

头文件:windows.h

函数原型:BOOLQueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount);

BOOLQueryPerformanceFrequency(LARGE_INTEGER *lpFrequency);

功能:前者获得的是CPU从开机以来执行的时钟周期数。后者用于获得你的机器一秒钟执行多少次,就是你的时钟周期。

补充:LARGE_INTEGER既可以是一个8字节长的整型数,也可以是两个4字节长的整型数的联合结构, 其具体用法根据编译器是否支持64位而定:

  1. typedef union_LARGE_INTEGER
  2. {
  3. struct
  4. {
  5. DWORD LowPart ;
  6. LONG HighPart;
  7. };
  8. LONGLONG QuadPart ;
  9. }LARGE_INTEGER;

用法

在进行定时之前,先调用QueryPerformanceFrequency()函数获得机器内部定时器的时钟频率,然后在需要严格定时的事件发生之前和发生之后分别调用QueryPerformanceCounter()函数,利用两次获得的计数之差及时钟频率,计算出事件经历的精确时间。

  1. LARGE_INTEGER  num;
  2. longlong start,end,freq;
  3. QueryPerformanceFrequency(&num);
  4. freq=num.QuadPart;
  5. QueryPerformanceCounter(&num);
  6. start= num.QuadPart;
  7. //…calculating…
  8. QueryPerformanceCounter(&num);
  9. end= num.QuadPart;
  10. printf("time=%d\n",(end-start)*1000/freq);

总结:这种方法的定时误差不超过1微秒,精度与CPU等机器配置有关,一般认为精度为透微秒级。在Windows平台下进行高精度计时的时候可以考虑这种方法。

6. gettimeofday()

Linux C函数。

头文件:sys/time.h

函数原型:int gettimeofday(struct timeval *tv,struct timezone *tz);

说明:其参数tv是保存获取时间结果的结构体,参数tz用于保存时区结果(若不使用则传入NULL即可)。

timeval的定义为:

  1. struct timeval {
  2.   long tv_sec; // 秒数
  3.   long tv_usec; //微秒数
  4. }

可见该函数可用于在linux中获得微秒精度的时间。

用法

  1. struct timeval start,end;
  2. gettimeofday(&start, NULL );
  3. //…calculating…
  4. gettimeofday(&end, NULL );
  5. long timeuse =1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;
  6. printf("time=%f\n",timeuse /1000000.0);

总结:使用这种方式计时,精度可达微秒。经验证,在arm+linux的环境下此函数仍可使用。推荐。

7. RDTSC - 读取时间标签计数器

X86架构CPU汇编指令。

操作码:0F 31 指令:RDTSC

功能:将时间标签计数器读入 EDX:EAX寄存器中。

说明:在Pentium以上的CPU中,提供了一条机器指令RDTSC来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用:

  1. inline unsigned long longGetCycleCount()
  2. {
  3. __asm RDTSC
  4. }

如果编译器不允许直接用RDTSC的话,可以用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31:

  1. inline unsigned long long GetCycleCount()
  2. {
  3. __asm _emit 0x0F
  4. __asm _emit 0x31
  5. }

计算时还需要将得到的数字除以CPU的主频(单位GHZ),就能得到纳秒级的时间了。暂时我还没找到好的获得机器主频的方法,Windows平台下可以考虑用QueryPerformanceFrequency()函数,但这样一来就没办法在Linux下使用此方法。后来我考虑配合sleep函数,获取1秒中的机器周期数的方法来得到CPU主频。如果哪位有更好的方法,还请多多请教。

  1. #ifdef WIN32
  2. #include <windows.h>
  3. #else
  4. #include <sys/unistd.h>
  5. #endif
  6. inline unsigned long long GetNTime()
  7. {
  8. __asm("RDTSC");
  9. }
  10. static double hz=0.0;
  11. void init_timer()
  12. {
  13. longlong t1=GetNTime();
  14. #ifdef WIN32
  15. Sleep(1000);
  16. #else
  17. sleep(1);
  18. #endif
  19. longlong t=GetNTime()-t1;
  20. hz=(double)t/1000000000;
  21. printf("hz=%fGhz\n",hz);
  22. }
  23. long long u_timer(long long *t,int mode)
  24. {
  25. if(hz<0.001)
  26. init_timer();
  27. if(!mode)
  28. {
  29. *t=GetNTime();
  30. return0;
  31. }
  32. longlong t1=GetNTime()-*t;
  33. t1/=hz;
  34. longlong ns=t1%1000;
  35. longlong us=(t1/1000)%1000;
  36. longlong ms=(t1/1000000)%1000;
  37. longlong s=t1/1000000000;
  38. printf("time=");
  39. if(s!=0)
  40. printf("%llds",s);
  41. if(ms!=0)
  42. printf("%lldms",ms);
  43. if(us!=0)
  44. printf("%lldus",us);
  45. if(ns!=0)
  46. printf("%lldns",ns);
  47. printf("\n");
  48. *t=GetNTime();
  49. returnt1;
  50. }

总结:这种方法精确到纳秒,但缺点是非常短时间的计时会不稳定。最近因为项目需要,我也找了一下ARM+Linux平台上可以用的计时方法,后来选择了gettimeofday()。不知道ARM+Linux平台上有没有类似RDTSC的这种指令。

C语言中常用计时方法总结的更多相关文章

  1. String:(字符串)中常用的方法

    package stringyiwen; //字符串中常用的方法public class StringTest03 { public static void main(String[] args) { ...

  2. 大数据学习day13------第三阶段----scala01-----函数式编程。scala以及IDEA的安装,变量的定义,条件表达式,for循环(守卫模式,推导式,可变参数以及三种遍历方式),方法定义,数组以及集合(可变和非可变),数组中常用的方法

    具体见第三阶段scala-day01中的文档(scala编程基础---基础语法)  1. 函数式编程(https://www.cnblogs.com/wchukai/p/5651185.html): ...

  3. org.apache.commons.lang.StringUtils中常用的方法

    org.apache.commons.lang.StringUtils中常用的方法,这里主要列举String中没有,且比较有用的方法: 1. 检查字符串是否为空: static boolean isB ...

  4. String对象中常用的方法

    String对象中常用的方法   1.charCodeAt方法返回一个整数,代表指定位置字符的Unicode编码.strObj.charCodeAt(index)说明:index将被处理字符的从零开始 ...

  5. 项目中常用js方法整理common.js

    抽空把项目中常用js方法整理成了common.js,都是网上搜集而来的,大家一起分享吧. var h = {}; h.get = function (url, data, ok, error) { $ ...

  6. go 语言中常用的包

    来自学习go语言.pdf 译者刑星 ==== fmt 包fmt实现了格式化IO函数,这与c的printf和scanf类似,格式化短语派生于c %v 默认格式的值.当打印结构时,加号(%+v)会增加字段 ...

  7. 【java】开发中常用字符串方法

    java字符串的功能可以说非常强大, 它的每一种方法也都很有用. java字符串中常用的有两种字符串类, 分别是String类和StringBuffer类. Sting类 String类的对象是不可变 ...

  8. C语言中字符串存储方法

    众所周知,C语言中没有数据类型能够存储字符串, char数据类型仅仅能够存储一个字符的数据,那么在C语言中关于存储字符串这一难题我们改何去何从呢? 下面将详述相关的字符串存储方法; 1,使用字符数组存 ...

  9. day2 列表中常用的方法

    列表中有很多方法,下面来看看常用的方法,我们知道,字符串是以字符列表形式存储的.因此上面学习的字符串中的很多方法在列表中也有.     1.extend() extend()列表的扩展,把两个列表进行 ...

随机推荐

  1. POJ 3026 Borg Maze(Prim+bfs求各点间距离)

    题目链接:http://poj.org/problem?id=3026 题目大意:在一个y行 x列的迷宫中,有可行走的通路空格’  ‘,不可行走的墙’#’,还有两种英文字母A和S,现在从S出发,要求用 ...

  2. HDU 1043 Eight(反向BFS+打表+康托展开)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1043 题目大意:传统八数码问题 解题思路:就是从“12345678x”这个终点状态开始反向BFS,将各 ...

  3. Fiddler Web Session 列表(1)

    Web Session 列表 位置: Web Session 列表 位于Fiddler界面的左侧 ,是Fiddler所抓取到的所有Session会话的列表集合. Web Session 列表 栏名词解 ...

  4. Codeforces Round #393 (Div. 2) (8VC Venture Cup 2017 - Final Round Div. 2 Edition) E - Nikita and stack 线段树好题

    http://codeforces.com/contest/760/problem/E 题目大意:现在对栈有m个操作,但是顺序是乱的,现在每输入一个操作要求你输出当前的栈顶, 注意,已有操作要按它们的 ...

  5. Java 中(静态)变量、(静态)代码块的执行顺序

    Java 中(静态)变量.(静态)代码块的执行顺序 非原创 本文讨论 Java 中(静态)变量.(静态)代码块的执行顺序 首先创建 3 个类 1.Foo 类 public class Foo { pu ...

  6. Java List转换为字符串的几种方法

    Java List转换为字符串的几种方法 import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import ...

  7. ref:Struts2 命令执行系列回顾

    ref:http://www.zerokeeper.com/vul-analysis/struts2-command-execution-series-review.html Struts2 命令执行 ...

  8. HDU 6185 Covering

    矩阵快速幂. 一开始的思路是$dfs$出一个矩阵,$k[i][j]$表示这一行是状态$i$,将这一行填满,下一行是$j$状态的方案数.然后就可以矩阵快速幂了,但是矩阵大小是$16*16$的,超时了.. ...

  9. angular4 监听input框输入值的改变

    angular中一般控件会有change事件,但是如果某些控件没有这个事件 我们如何监听值的变化呢? 对于双向绑定的值,当值改变后监听事件有如下写法: 1. 如果是ngModel可以用ngModelC ...

  10. hihocoder #1580 : Matrix (DP)

    #1580 : Matrix 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Once upon a time, there was a little dog YK. On ...