Measuring amount of CPU time taken by a piece of code, in C on Unix/Linux
clock()可以用作可靠的API来测量CPU执行代码片段所花费的时间吗?当使用times()/ clock()验证时,两者似乎都不能精确测量所花费的CPU时间。
首先,可以使用API?? clock()/ times()来测量函数/代码片段的执行时间,如下例所示?有没有更好更可靠的选择?该机制适用于Linux,HP-UX,IBM-AIX和Sun Solaris,因为我们需要测量(和比较)所有这些平台上的一段代码的性能。
请建议。另外,如果我遗漏了任何微不足道的事,请告诉我。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | bbb@m_001:/tmp/kk1$ ./perf_clock 102400 {clock(): S 0 E 0 D 0.0000000000} bbb@m_001:/tmp/kk1$ ./perf_clock 204800 {clock(): S 0 E 10000 D 0.0100000000} bbb@m_001:/tmp/kk1$ cat perf_clock.c #include <stdio.h> #include <string.h> #include <time.h> #include <unistd.h> void test_clock(char* sbuf, int* len){ clock_t start, end; int i=0; start = clock(); while(i++ < 500) memset((char*)sbuf,0,*len); end = clock(); printf("{clock(): S %10lu E %10lu D %15.10f} ", start,end,(end-start)/(double) CLOCKS_PER_SEC); } int main(int argc,char* argv[]) { int len=atoi(argv[1]); char *sbuf=(char*)malloc(len); test_clock(sbuf,&len); free(sbuf); return 0; } |
结果似乎说memset()一个100 KB的块,500次,没有时间花。还是说它在几微秒内无法测量?
实际上,它不是memset()而是另一个函数[准备一个大小约1MB的巨大结构,mallocs这个结构的副本,Oracle DB选择并使用来自DB的数据填充这些结构]我试图测量。即使这显示0滴答,这也让我感到困惑。
谢谢!
在最近的Linux(*)上。您可以从/ proc文件系统获取此信息。在文件
如果要基于每个线程查看数据,则应该引用文件
要将jiffies转换为微秒,可以使用以下命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | define USEC_PER_SEC 1000000UL long long jiffies_to_microsecond(long long jiffies) { long hz = sysconf(_SC_CLK_TCK); if (hz <= USEC_PER_SEC && !(USEC_PER_SEC % hz)) { return (USEC_PER_SEC / hz) * jiffies; } else if (hz > USEC_PER_SEC && !(hz % USEC_PER_SEC)) { return (jiffies + (hz / USEC_PER_SEC) - 1) / (hz / USEC_PER_SEC); } else { return (jiffies * USEC_PER_SEC) / hz; } } |
如果你关心的只是每个进程的统计信息,那么
* - 我不确定何时引入了stat文件。您需要验证您的系统是否具有该功能。
我会尝试使用
同时检查
我会尝试将时间与shell的
您还应该考虑编译器可能正在优化循环。由于memset不依赖于循环变量,因此编译器肯定会尝试应用称为循环不变代码运动的优化。
我还要提醒一下,10MB可能的高速缓存清除将真正是1.25或250万CPU操作,因为memset肯定以4字节或8字节的数量写入。虽然我怀疑这可以在不到一微秒的时间内完成,因为存储有点贵,而且100K增加了一些L1缓存压力,你所说的每纳秒不超过一次操作,这并不难以维持一个多GHz CPU。
人们可以想象600 nS可以完成1个时钟滴答,但我也会担心这个问题。
您可以使用
或者您可以使用linux
进程/线程的资源使用仅由OS定期更新。完全有可能在下一次更新之前完成代码片段,从而产生零资源使用差异。无法说出有关HP或AIX的任何内容,请参考Sun的Solaris性能和工具书。对于Linux,您需要查看oprofile和更新的perf工具。在剖析方面,valgrind将会有很大帮助。
惠普关于高分辨率计时器页面的一些信息。此外,http://www.fftw.org/cycle.h中也使用了相同的技巧
必须确认这是否真的可以成为解决方案。
在HP-UX 11.31上测试的示例prog
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | bbb@m_001/tmp/prof > ./perf_ticks 1024 ticks-memset {func [1401.000000] inline [30.000000]} noop [9.000000] bbb@m_001/tmp/prof > cat perf_ticks.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <unistd.h> #include"cycle.h" /* one from http://www.fftw.org/cycle.h */ void test_ticks(char* sbuf, int* len){ memset((char*)sbuf,0,*len); } int main(int argc,char* argv[]){ int len=atoi(argv[1]); char *sbuf=(char*)malloc(len); ticks t1,t2,t3,t4,t5,t6; t1 =getticks(); test_ticks(sbuf,&len); t2 =getticks(); t3 =getticks(); memset((char*)sbuf,0,len); t4 =getticks(); t5=getticks();;t6=getticks(); printf("ticks-memset {func [%llf] inline [%llf]} noop [%llf] ", elapsed(t2,t1),elapsed(t4,t3),elapsed(t6,t5)); free(sbuf); return 0; } bbb@m_001/tmp/prof > |