c/c++测试函数的运行时间(八种方法)-阿里云开发者社区

开发者社区> 茶花盛开> 正文

c/c++测试函数的运行时间(八种方法)

简介: c/c++测试函数的运行时间(八种方法)
+关注继续查看

目前,存在着各种计时函数,一般的处理都是先调用计时函数,记下当前时间tstart,然后处理一段程序,再调用计时函数,记下处理后的时间tend,再tend和tstart做差,就可以得到程序的执行时间,但是各种计时函数的精度不一样.下面对各种计时函数,做些简单记录.

void foo()
{
    long i;
    for (i=0;i<100000000;i++)
    {
        long a= 0;
        a = a+1;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

方法1,time()获取当前的系统时间,返回的结果是一个time_t类型,其实就是一个大整数,其值表示从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数.

void test1()
{
    time_t start,stop;
    start = time(NULL);
    foo();//dosomething
    stop = time(NULL);
    printf("Use Time:%ld\n",(stop-start));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

方法2,clock()函数返回从“开启这个程序进程”到“程序中调用clock()函数”时之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock)常量CLOCKS_PER_SEC,它用来表示一秒钟会有多少个时钟计时单元。

void test2()
{
    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));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

如果你想学习C/C++可以来这个群,首先是三三零,中间是八五九,最后是七六六,里面有大量的学习资料可以下载。

方法3,timeGetTime()函数以毫秒计的系统时间。该时间为从系统开启算起所经过的时间,是windows api

void test3()
{
    DWORD t1,t2;
    t1 = timeGetTime();
    foo();//dosomething
    t2 = timeGetTime();
    printf("Use Time:%f\n",(t2-t1)*1.0/1000);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

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

void test4()
{
    LARGE_INTEGER t1,t2,tc;
    QueryPerformanceFrequency(&tc);
    QueryPerformanceCounter(&t1);
    foo();//dosomething
    QueryPerformanceCounter(&t2);
    printf("Use Time:%f\n",(t2.QuadPart - t1.QuadPart)*1.0/tc.QuadPart);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

方法5,GetTickCount返回(retrieve)从操作系统启动到现在所经过(elapsed)的毫秒数,它的返回值是DWORD

void test5()
{
    DWORD t1,t2;
    t1 = GetTickCount();
    foo();//dosomething
    t2 = GetTickCount();
    printf("Use Time:%f\n",(t2-t1)*1.0/1000);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

方法6,RDTSC指令,在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的频率
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

方法7,gettimeofday() linux环境下的计时函数,int gettimeofday ( struct timeval * tv , struct timezone * tz ),gettimeofday()会把目前的时间有tv所指的结构返回,当地时区的信息则放到tz所指的结构中.

//timeval结构定义为:
struct timeval{
long tv_sec; /*秒*/
long tv_usec; /*微秒*/
};
//timezone 结构定义为:
struct timezone{
int tz_minuteswest; /*和Greenwich 时间差了多少分钟*/
int tz_dsttime; /*日光节约时间的状态*/
};
void test7()
{
    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);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

方法8,linux环境下,用RDTSC指令计时.与方法6是一样的.只不过在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的频率
}

  • 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

 总结,方法1,2,7,8可以在linux环境下执行,方法1,2,3,4,5,6可以在windows环境下执行.其中,timeGetTime()和GetTickCount()的返回值类型为DWORD,当统计的毫妙数过大时,将会使结果归0,影响统计结果. 
测试结果,windows环境下,主频为1.6GHz,单位为秒.

1 Use Time:0 
2 Use Time:0.390000 
3 Use Time:0.388000 
4 Use Time:0.394704 
5 Use Time:0.407000 
6 Use Time:0.398684

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
【C/C++】cctype中的字符函数
c++中头文件为 ,c中则是。 这些函数以一个数值或者字符作为参数并返回布尔值true或flase,或者是字符,具体因函数不同 这里面的函数可以分为两类: 判断函数 它们检查输入参数是否属于某个类别: isalnum...
683 0
Flink运行时之生成作业图
生成作业图 在分析完了流处理程序生成的流图(StreamGraph)以及批处理程序生成的优化后的计划(OptimizedPlan)之后,下一步就是生成它们面向Flink运行时执行引擎的共同抽象——作业图(JobGraph)。
1639 0
C++函数对象
  原文:http://blog.csdn.net/ggggqqqqihc/article/details/1727020   标准库里的count_if可以统计容器中满足特定条件的元素的个数。例如要统计一个整数vector——ivec中正数的个数,可以先写一个返回类型为bool,含有一个int参数的条件函数: bool pred(int val){ return val>0; }    之后可以用count_if(ivec.begin(),ivec.end(),pred)计算出正整数的个数。
481 0
+关注
茶花盛开
web前端新手群291851189
218
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载