摘要:本文详细的讨论了在windows平台中,测量程序运行时间的几个函数,GetTickCount, QueryPerformanceCounter和RDTSC,并给出示例代码。
  算法的好坏有好多评价指标,其中一个重要的指标是时间复杂度。如果两个程序完成一个同样的任务,即功能相同,处理的数据相同,那么运行时间较短者为优。操作系统和库函数一般都提供了对时间测量的函数,这么函数一般都会返回一个代表当前时间的数值,通过在运行某个程序或某段代码之前调用一次时间函数来得到一个数值,在程序或者代码段运行之后再调用一次时间函数来得到另一个数值,将后者减去前者即为程序的运行时间。
 在windwos平台(指windwow95及以后的版本,下同),常用的用于测量时间的函数或方法有三种:1.API函数GetTickCount或C函数clock, 2.API函数QueryPerformanceCounter, 3:汇编指令RDSTC
1.API函数GetTickCount:
函数原形:DWORD GetTickCount(VOID);
该函数取回从电脑开机至现在的毫秒数,即每个时间单位为1毫秒。他的分辨率比较低,常用在测量用时较长程序,如果你的程序用时为100毫秒以上,可以使用这个函数.另一个和GetTickCount类似的函数是clock,该函数的回的时间的单位的是CLOCKS_PER_SEC,在windows95/2000操作系统,该值是1000,也就是说,在windows平台,这两个函数的功能几乎完全相同。
2.API函数QueryPerformanceCounter:
函数原形:BOOL QueryPerformanceCounter( LARGE_INTEGER *lpPerformanceCount);该函数取回当前的高分辨值performance计数器,用一个64bit数来表示。如果你的硬件不支持高分辨performance计数器,系统可能返加零。不像GetTickCount,每个计数器单位表示一个固定的时间1毫秒,为了知道程序确切的执行时间,你需要调用函数QueryPerformanceFrequency来得到每秒performance计数器的次数,即频率。
3.汇编指令RDTSC:
RDTSC 指令读取CPU内部的“时间戳(TimeStamp)",它是一个64位无符号数计数器,这条指令执行完毕后,存储在EDX:EAX寄存中。该指令从intel奔腾CPU开始引入,一些老式的CPU不支持该指令,奔腾后期的CPU包括AMD的CPU均支持这条指令。和QueryPerformanceCounter类似,要想知道程序的确实的执行时间,必须知道CPU的频率,即平常所说的CPU的主频。不幸的是没有现成的函数可以得到CPU的频率。一种办法可行的办法延时一段指定时间,时间的测量可以用QueryPerformanceCounter来做,在这段时间的开始和结束调用RDTSC,得到其时钟数的差值,然后除以这段时间的的秒数就可以了。
 
下面的代码给出使用3个函数封装和测试代码,用RDTSC指令来计时的代码参考了一个Ticktest的源代码,作者不详。
getTime1,使用GetTickCount返回一个表示当前时间的值,单位秒。
getTime2,和getTime1类似,精度更高。
getTime3,返回一个64bit的一个计数器,欲转换为秒,需除以CPU频率。示例代码见函数test3.

#include "stdafx.h"
#include "windows.h"
#include "tchar.h"
double getTime1()
{DWORD t=GetTickCount();return (double)t/1000.00;
}
double getTime2() //使用高精度计时器
{      static LARGE_INTEGER s_freq;LARGE_INTEGER performanceCount;double t;if (s_freq.QuadPart==0){if ( !QueryPerformanceFrequency( &s_freq))return 0;}QueryPerformanceCounter( &performanceCount );t=(double)performanceCount.QuadPart / (double)s_freq.QuadPart;return t;
}
void test1()
{double t1,t2;t1=getTime1();Sleep(1000);t2=getTime1()-t1;printf("It take %.8f second\n",t2);//你们把/n贴代码里表示很高级么
}
void test2()
{double t1,t2;t1=getTime2();Sleep(1000);t2=getTime2()-t1;printf("It take %.8f second\n",t2);
}
inline BOOL isNTOS() //检测是否运行在NT操作系统
{typedef BOOL (WINAPI *lpfnGetVersionEx) (LPOSVERSIONINFO);static int bIsNT=-1;if (bIsNT!=1)return (BOOL)bIsNT;// Get Kernel handleHMODULE hKernel32 = GetModuleHandle(_T("KERNEL32.DLL"));if (hKernel32 == NULL)return FALSE;#ifdef _UNICODElpfnGetVersionEx lpGetVersionEx = (lpfnGetVersionEx) GetProcAddress(hKernel32, _T("GetVersionExW"));#elselpfnGetVersionEx lpGetVersionEx = (lpfnGetVersionEx) GetProcAddress(hKernel32, _T("GetVersionExA"));#endifif (lpGetVersionEx){OSVERSIONINFO osvi;memset(&osvi, 0, sizeof(OSVERSIONINFO));osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);if (!lpGetVersionEx(&osvi))bIsNT=FALSE;elsebIsNT=(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT);}else{//Since GetVersionEx is not available we known that //we are running on NT 3.1 as all modern versions of NT and//any version of Windows 95/98 support GetVersionExbIsNT=TRUE;}return bIsNT;
}
inline static BOOL checkRDSTC() //检测CPU是否支持RDSTC指令
{static int bHasRDSTC= -1;SYSTEM_INFO sys_info;if ( bHasRDSTC !=-1 )return (BOOL)bHasRDSTC;GetSystemInfo(&sys_info);if (sys_info.dwProcessorType==PROCESSOR_INTEL_PENTIUM){try{_asm{_emit 0x0f                           ; rdtsc     _emit 0x31}}catch (...)       // Check to see if the opcode is defined.{bHasRDSTC=FALSE; return FALSE;}// Check to see if the instruction ticks accesses something that changes.volatile ULARGE_INTEGER ts1,ts2;_asm{xor eax,eax_emit 0x0f                                  ; cpuid_emit 0xa2_emit 0x0f                                  ; rdtsc_emit 0x31mov ts1.HighPart,edxmov ts1.LowPart,eaxxor eax,eax_emit 0x0f                                  ; cpuid_emit 0xa2_emit 0x0f                                  ; rdtsc_emit 0x31mov ts2.HighPart,edxmov ts2.LowPart,eax}// If we return true then there's a very good chance it's a real RDTSC instruction!if (ts2.HighPart>ts1.HighPart)bHasRDSTC=TRUE;else if (ts2.HighPart==ts1.HighPart && ts2.LowPart>ts1.LowPart)bHasRDSTC=TRUE;else{ printf("RDTSC instruction NOT present./n");bHasRDSTC=FALSE;}}elsebHasRDSTC=FALSE;return bHasRDSTC;
}
//***********************************************
void getTime3( LARGE_INTEGER *pTime) //返加当前CPU的内部计数器
{if (checkRDSTC()){volatile ULARGE_INTEGER ts;//on NT don't bother disabling interrupts as doing//so will generate a priviledge instruction exceptionif (!isNTOS())_asm cli//----------------      _asm{xor eax,eax//-------------save rigisterpush ebxpush ecx_emit 0x0f                                  ; cpuid - serialise the processor_emit 0xa2//------------_emit 0x0f                                  ; rdtsc_emit 0x31mov ts.HighPart,edxmov ts.LowPart,eaxpop ecxpop ebx}//-----------------if (!isNTOS())_asm      sti//---------        pTime->QuadPart=ts.QuadPart;}elsepTime->QuadPart=0;
}
// maxDetermainTime:最大测定时间,单位毫秒,在首次调用该函数时,
// 将花费maxDetermineTime的时间来测定CPU频率,以后的调用将直接返加静态变量的值
double GetCPUFrequency(DWORD maxDetermineTime )
{static double CPU_freq;LARGE_INTEGER period,t1,t2;register LARGE_INTEGER goal,current;if (CPU_freq>1000)      //this value have been initilizationreturn CPU_freq;if (!QueryPerformanceFrequency(&period) || !checkRDSTC()){CPU_freq=-1.00;return CPU_freq;}QueryPerformanceCounter(&goal);goal.QuadPart += period.QuadPart * maxDetermineTime/1000;getTime3( &t1);  //开始计时do    //延时maxDetermineTime毫秒{QueryPerformanceCounter(¤t);} while(current.QuadPart<goal.QuadPart);getTime3(&t2);      //结束计时CPU_freq=double((t2.QuadPart-t1.QuadPart)*1000/maxDetermineTime);char buff[100];sprintf(buff,"Estimated the processor clock frequency =%gHz/n",CPU_freq);::MessageBox(NULL,buff,"",MB_OK);return CPU_freq;
}
void test3()
{LARGE_INTEGER t,t1,t2;double f1,f2;GetCPUFrequency(100); //花费0.1秒时间计算CPU频率f1=getTime2();getTime3(&t1);Sleep(1000);getTime3(&t2);f2=getTime2();t.QuadPart=t2.QuadPart-t1.QuadPart;printf("It take %.8f second by getTime3\n",(double)t.QuadPart/GetCPUFrequency(100));printf("It take %.8f second by getTime2\n",f2-f1);
}
int main(int argc, char* argv[])
{test1();test2();test3();return 0;
}

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/wzdworld001/archive/2007/06/08/1644111.aspx

测量程序运行时间的几个函数相关推荐

  1. 如何测量程序运行时间?

    整理:黄工 素材来源:最后一个Bug 程序的运行时间,对一个系统比较重要.有的地方要求精确延时Nus,有的地方要求程序运行时间不能超过Nus. 所以,今天给大家分享一些常见测量程序(任务)运行时间的方 ...

  2. 运行时间_一种简单、实用的测量程序运行时间的方法

    点击上方「嵌入式大杂烩」,选择「置顶公众号」第一时间查看嵌入式笔记! 前言 平时我们可能很少去关注程序运行的时间,但是在一些情况下可能需要对程序进行一个整体的复盘.优化. 那么,程序运行的时间就是一个 ...

  3. 一种简单、实用的测量程序运行时间的方法

    前言 平时我们可能很少去关注程序运行的时间,但是在一些情况下可能需要对程序进行一个整体的复盘.优化. 那么,程序运行的时间就是一个可以考虑的方面,可以测一下某些代码块.函数.算法的运行时间,然后整体考 ...

  4. java 测量程序运行时间

    主类 测量运行时间 public class Time {public void test1() { // --第一种是以毫秒为单位计算的. long startTime=System.current ...

  5. C#测量程序运行时间及cpu使用时间(转)

    对一个服务器程序想统计每秒可以处理多少数据包,要如何做?答案是用处理数据包的总数,除以累记处理数据包用的时间.这里要指出的是, 运行一段程序,使用的cpu时间,跟实际运行的时间是不一样的.附例如下: ...

  6. C语言测量程序运行时间

    有时候希望得到运行某个模块的具体用时,如何实现呢 clock()是C/C++中的计时函数,而与其相关的数据类型是clock_t.在MSDN中,查得对clock函数定义如下: clock_t clock ...

  7. systick 时间修改_如何用SysTick实现测量程序运行时间

    在实际的项目开发过程中,常常遇到需要得到一段代码的运行时间,通常的方法是用示波器来测量,这篇博文将用SysTick来实现精确测量程序运行的时间.STM32F4的内核定时器SysTick是一个24位的定 ...

  8. C++ 测量程序运行时间 任务管理看内存

    /** timer.cpp** Created on: 2014年12月28日* Author: judyge*/#include<cstring> #include<iomanip ...

  9. 运行时间_如何测量嵌入式软件运行时间?

    整理:黄工 素材来源:最后一个Bug 程序的运行时间,对一个系统比较重要.有的地方要求精确延时Nus,有的地方要求程序运行时间不能超过Nus. 所以,今天给大家分享一些常见测量程序(任务)运行时间的方 ...

最新文章

  1. A. 位运算符的应用---管理一组事务的开关状态
  2. php 解决方案,php优化解决方案
  3. python英语单词库-python-data-英语单词
  4. 【推荐】查找一代用户出口Userexit
  5. 【SpringBoot 2】(七)请求处理——映射 常用注解 方法参数的小技巧
  6. python中集合的元素可以是任意数据类型_Python数据类型之列表
  7. 会声会影x4素材_如何利用会声会影制作抖音短视频
  8. 【微信小程序】ColorUI——一个多彩漂亮的UI组件库
  9. KindEditor上传图片
  10. android 外文翻译,Android外文文献翻译.doc
  11. Excel应用技巧之二——常用函数
  12. 计算机标准体重计算公式,项目2:就拿胖子说事---(2)计算出标准体重,当超重时,请给出提示...
  13. APP上查个人信用报告靠谱吗?
  14. ESP8266_设置AP模式,WiFi名称密码
  15. pdo mysql num rows_PDO参数说明
  16. gaussDB200 单节点安装
  17. LCR测试仪与阻抗分析仪有何不同?测试软件怎么选?
  18. js 数字转人民币大写
  19. 易地推招生拓客分享:如何让社群招生成为培训机构招生利器?
  20. 20个常用Python运维库模块及工具

热门文章

  1. 从零开始实现一个简易的Java MVC框架(九)--优化MVC代码
  2. 锁Lock,主要是重入锁和读写锁
  3. 数据库操作:MFC连接与MYSQL
  4. QML 可以多选ComboBox的实现
  5. iOS百度地图的相关开发(一)
  6. 解决UnicodeDecodeError: 'ascii' codec can't decod...
  7. 利用memcache来保存tomcat的session会话
  8. linux如何加入windows域
  9. 德国黑客使用租用的计算机资源攻击散列算法
  10. Netbeans 安装和配置 C/C++ 支持