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

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

void foo()
{
    long i;
    for (i=0;i<100000000;i++)
    {
        long a= 0;
        a = a+1;
    }
}

方法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));
}

方法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));
}

如果你想学习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);
}

方法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);
}

方法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);
}

方法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的频率
}

方法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);
}

方法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,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

时间: 2024-10-10 11:54:39

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

HTTP/1.1协议中共定义了八种方法

HTTP/1.1协议中共定义了八种方法(有时也叫"动作")来表明Request-URI指定的资源的不同操作方式: 1.OPTIONS 返回服务器针对特定资源所支持的HTTP请求方法.也可以利用向Web服务器发送'*'的请求来测试服务器的 功能性,如获取当前URL所支持的方法.若请求成功,则它会在HTTP头中包含一个名为"Allow"的头,值是所支持 的方法,如"GET,POST". 2.HEAD 向服务器索要与GET请求相一致的响应,只不过响应体

selenium定位元素的八种方法

web driver提供了八种元素定位的方法: id, name, class name, tag name, link text, partial link text, xpath, css selector 如百度首页,百度一下按钮的元素信息 <input type="submit" id="su" value="百度一下" class="bg s_btn"> 百度首页新闻的页面的元素信息 <a href

清除浮动的八种方法

清除浮动是每一个 web前台设计师必须掌握的机能.css清除浮动大全,共8种方法. 浮动会使当前标签产生向上浮的效果,同时会影响到前后标签.父级标签的位置及 width height 属性.而且同样的代码,在各种浏览器中显示效果也有可能不相同,这样让清除浮动更难了.解决浮动引起的问题有多种方法,但有些方法在浏览器兼容性方面还有问题. 下面总结8种清除浮动的方法(测试已通过 ie chrome firefox opera,后面三种方法只做了解就可以了): 1,父级div定义 height 复制代码

CSS 隐藏元素的八种方法

前言 总括: 本文详细讲述了在网页中用CSS隐藏元素的七种方法. 原文博客地址:从隐藏元素谈起 知乎专栏&&简书专题:前端进击者(知乎)&&前端进击者(简书) 博主博客地址:Damonare的个人博客 念念不忘,必有回响;有一口气,点一盏灯. 正文 说起隐藏元素我想每一个前端er都能说起几种,但能说全的我想就不是很多了.博主总结了几种隐藏元素的方法,总结如下: 1 div{ 2 3 overflow:hidden 4 opacity:0: 5 visibility:hidd

IOS获取设备唯一标识的八种方法

免责声明:本文章来源于其他博客整理 参考:http://www.2cto.com/kf/201308/237648.html 参考:http://www.2cto.com/kf/201311/255684.html 在iOS系统中,获取设备唯一标识的方法有很多: 一.UDID(Unique Device Identifier) UDID的全称是Unique Device Identifier,它就是苹果IOS设备的唯一识别码,它由40个字符的字母和数字组成(越狱的设备通过某些工具可以改变设备的U

iOS - Animation 八种方法

一.//UIView动画 //能够做动画的属性, feame, center, bounds, alpha, transfom, backgroundcolor //iOS4.0 之前如果想做动画, 必须放在开始可提交之前才有效 //对属性更改值是有效值, 最终会对视图作出修改 //开始动画 [UIView beginAnimations:nil context:nil]; //1.设置动画持续的时间 --- 单位 秒 [UIView setAnimationDuration:2]; //2.设

数据库优化的八种方法

注:此文复制而来,只为便于学习! 1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽可能小. 例如,在定义邮政编码这个字段时,如果将其设置为CHAR(255),显然给数据库增加了不必要的空间,甚至使用VARCHAR这种类型也是多余的,因为CHAR(6)就可以很好的完成任务了.同样的,如果可以的话,我们应该使用MEDIUMINT而不是BIGIN来定义

提高情商的八种方法

1.学会划定恰当的心理界限,这对每个人都有好处. 你也许自认为与他人界限不明是一件好事,这样一来大家能随心所欲地相处,而且相互之间也不用激烈地讨价还价.这听起来似乎有点道理,但它的不利之处在于,别人经常伤害了你的感情而你却不自知. 其实仔细观察周遭你不难发现,界限能力差的人易于患上病态恐惧症,他们不会与侵犯者对抗,而更愿意向第三者倾诉.如果我们是那个侵犯了别人心理界限的人,发现事实的真相后,我们会感觉自己是个冷血的大笨蛋.同时我们也会感到受伤害,因为我们既为自己的过错而自责,又对一个第三者卷进来

判断中文字符的八种方法C#

软件开发技术交流,同学习共进步,欢迎加群, 群号:169600532  前段时间看见一些判断中文字符的方法,特整理出来,供以后用时方便 方法一 在unicode 字符串中,中文的范围是在4E00..9FFF:CJK Unified Ideographs. 通过对字符的unicode编码进行判断来确定字符是否为中文. protected bool IsChineseLetter(string input,int index) { int code = 0; int chfrom = Convert