queryperformancefrequencyjava中的返回值是什么hz吗

博客分类:
C语言获取系统时间的几种方式

  C语言获取系统时间的几种方式
  C语言中如何获取时间?精度如何?
  1 使用time_t time( time_t * timer ) 精确到秒
  2 使用clock_t clock() 得到的是CPU时间 精确到1/CLOCKS_PER_SEC秒
  3 计算时间差使用double difftime( time_t timer1, time_t timer0 )
  4 使用DWORD GetTickCount() 精确到毫秒
  5 如果使用MFC的CTime类,可以用CTime::GetCurrentTime() 精确到秒
  6 要获取高精度时间,可以使用
  BOOL QueryPerformanceFrequency(LARGE_INTEGER *lpFrequency)
  获取系统的计数器的频率
  BOOL QueryPerformanceCounter(LARGE_INTEGER *lpPerformanceCount)
  获取计数器的值
  然后用两次计数器的差除以Frequency就得到时间。
  7 Multimedia Timer Functions
  The following functions are used with multimedia timers.
  timeBeginPeriod/timeEndPeriod/timeGetDevCaps/timeGetSystemTime
  //*********************************************************************
  //用标准C实现获取当前系统时间的函数
  一.time()函数
  time(&rawtime)函数获取当前时间距日的秒数,以秒计数单位,存于rawtime 中。
  #include "time.h"
  void main ()
  struct tm *
  time ( &rawtime );
  timeinfo = localtime ( &rawtime );
  printf ( "\007The current date/time is: %s", asctime (timeinfo) );
  exit(0);
  =================
  #include -- 必须的时间函数头文件
  time_t -- 时间类型(time.h 定义是typedef long time_t; 追根溯源,time_t是long)
  struct tm -- 时间结构,time.h 定义如下:
  int tm_
  int tm_
  int tm_
  int tm_
  int tm_
  int tm_
  int tm_
  int tm_
  int tm_
  time ( &rawtime ); -- 获取时间,以秒计,从1970年1月一日起算,存于rawtime
  localtime ( &rawtime ); -- 转为当地时间,tm 时间结构
  asctime ()-- 转为标准ASCII时间格式:
  星期 月 日 时:分:秒 年
  -----------------------------------------------------------------------------
  二.clock()函数,用clock()函数,得到系统启动以后的毫秒级时间,然后除以CLOCKS_PER_SEC,就可以换成“秒”,标准c函数。
  clock_t clock ( void );
  #include
  clock_t t = clock();
  long sec = t / CLOCKS_PER_SEC;
  他是记录时钟周期的,实现看来不会很精确,需要试验验证;
  ---------------------------------------------------------------------------
  三.gettime(&t); 据说tc2.0的time结构含有毫秒信息
  #include
  #include
  int main(void)
  gettime(&t);
  printf("The current time is: %2d:%02d:%02d.%02d\n",
  t.ti_hour, t.ti_min, t.ti_sec, t.ti_hund);
  return 0;
  time 是一个结构体,, 其中成员函数 ti_hund 是毫秒。。。
  --------------------------------------------------------------------------------
  四.GetTickCount(),这个是windows里面常用来计算程序运行时间的函数;
  DWORD dwStart = GetTickCount();
  //这里运行你的程序代码
  DWORD dwEnd = GetTickCount();
  则(dwEnd-dwStart)就是你的程序运行时间, 以毫秒为单位
  这个函数只精确到55ms,1个tick就是55ms。
  --------------------------------------------------------------------------------
  五.timeGetTime()t,imeGetTime()基本等于GetTickCount(),但是精度更高
  DWORD dwStart = timeGetTime();
  //这里运行你的程序代码
  DWORD dwEnd = timeGetTime();
  则(dwEnd-dwStart)就是你的程序运行时间, 以毫秒为单位
  虽然返回的值单位应该是ms,但传说精度只有10ms。
  =========================================
  //*****************************************************************Unix
  ##unix时间相关,也是标准库的
  //*********************************************************************
  1.timegm函数只是将struct tm结构转成time_t结构,不使用时区信息;
  time_t timegm(struct tm *tm);
  2.mktime使用时区信息
  time_t mktime(struct tm *tm);
  timelocal 函数是GNU扩展的与posix函数mktime相当
  time_t timelocal (struct tm *tm);
  3.gmtime函数只是将time_t结构转成struct tm结构,不使用时区信息;
  struct tm * gmtime(const time_t *clock);
  4.localtime使用时区信息
  struct tm * localtime(const time_t *clock);
  1.time获取时间,stime设置时间
  time_t t;
  t = time(&t);
  2.stime其参数应该是GMT时间,根据本地时区设置为本地时间;
  int stime(time_t *tp)
  3.UTC=true 表示采用夏时制;
  4.文件的修改时间等信息全部采用GMT时间存放,不同的系统在得到修改时间后通过localtime转换成本地时间;
  5.设置时区推荐使用setup来设置;
  6.设置时区也可以先更变/etc/sysconfig/clock中的设置 再将ln -fs /usr/share/zoneinfo/xxxx/xxx /etc/localtime 才能重效
  time_t只能表示68年的范围,即mktime只能返回这一段范围的time_t
  看看你的系统是否有time_t64,它能表示更大的时间范围
  //***************************************************************windows
  ##Window里面的一些不一样的
  //*********************************************************************
  一.CTime () 类
  VC编程一般使用CTime类 获得当前日期和时间
  CTime t = GetCurrentTime();
  SYSTEMTIME 结构包含毫秒信息
  typedef struct _SYSTEMTIME {
  WORD wY
  WORD wM
  WORD wDayOfW
  WORD wD
  WORD wH
  WORD wM
  WORD wS
  WORD wM
  } SYSTEMTIME, *PSYSTEMTIME;
  SYSTEMTIME t1;
  GetSystemTime(&t1)
  CTime curTime(t1);
  WORD ms = t1.wM
  SYSTEMTIME sysTm;
  ::GetLocalTime(&sysTm);
  在time.h中的_strtime() //只能在windows中用
  char t[11];
  _strtime(t);
  puts(t);
  //*****************************
  获得当前日期和时间
  CTime tm=CTime::GetCurrentTime();
  CString str=tm.Format("%Y-%m-%d");
  在VC中,我们可以借助CTime时间类,获取系统当前日期,具体使用方法如下:
  CTime t = CTime::GetCurrentTime(); //获取系统日期,存储在t里面
  int d=t.GetDay(); //获得当前日期
  int y=t.GetYear(); //获取当前年份
  int m=t.GetMonth(); //获取当前月份
  int h=t.GetHour(); //获取当前为几时
  int mm=t.GetMinute(); //获取当前分钟
  int s=t.GetSecond(); //获取当前秒
  int w=t.GetDayOfWeek(); //获取星期几,注意1为星期天,7为星期六
  二.CTimeSpan类
  如果想计算两段时间的差值,可以使用CTimeSpan类,具体使用方法如下:
  CTime t1( , 22, 15, 0 );
  CTime t = CTime::GetCurrentTime();
  CTimeSpan span=t-t1; //计算当前系统时间与时间t1的间隔
  int iDay=span.GetDays(); //获取这段时间间隔共有多少天
  int iHour=span.GetTotalHours(); //获取总共有多少小时
  int iMin=span.GetTotalMinutes();//获取总共有多少分钟
  int iSec=span.GetTotalSeconds();//获取总共有多少秒
  ------------------------------------------------------------------------------
  三._timeb()函数
  _timeb定义在SYS\TIMEB.H,有四个fields
  dstflag
  millitm
  time
  timezone
  void _ftime( struct _timeb *timeptr );
  struct _
  _ftime( &timebuffer );
  取当前时间:文档讲可以到ms,有人测试,好象只能到16ms!
  四.设置计时器
  定义TIMER ID
  #define TIMERID_JISUANFANGSHI 2
  在适当的地方设置时钟,需要开始其作用的地方;
  SetTimer(TIMERID_JISUANFANGSHI,200,NULL);
  在不需要定时器的时候的时候销毁掉时钟
  KillTimer(TIMERID_JISUANFANGSHI);
  对应VC程序的消息映射
  void CJisuan::OnTimer(UINT nIDEvent)
  {switch(nIDEvent)}
  ---------------------------------------------------------------------------------------
  ##如何设定当前系统时间---------------------------------------windows
  SYSTEMTIME m_myLocalTime,*lpSystemT
  m_myLocalTime.wYear=2003;
  m_myLocalTime.wM;
  m_myLocalTime.wDay=1;
  m_myLocalTime.wHour=0;
  m_myLocalTime.wMinute=0;
  m_myLocalTime.wS
  m_myLocalTime.wM
  lpSystemTime=&m_myLocalT
  if( SetLocalTime(lpSystemTime) ) //此处换成 SetSystemTime( )也不行
  MessageBox("OK !");
  else
  MessageBox("Error !");
  SYSTEMTIME m_myLocalTime,*lpSystemT
  m_myLocalTime.wYear=2003;
  m_myLocalTime.wM;
  m_myLocalTime.wDay=1;
  lpSystemTime=&m_myLocalT
  if( SetDate(lpSystemTime) ) //此处换成 SetSystemTime( )也不行
  MessageBox("OK !");
  else
  MessageBox("Error !");
  本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/khuang2008/archive//3483274.aspx
  一种制作微秒级精度定时器的方法
  当使用定时器时,在很多情况下只用到毫秒级的时间间隔,所以只需用到下面的两种常用方式就满足要求了。一是用SetTimer函数建立一个定时器后,在程序中通过处理由定时器发送到线程消息队列中的WM_TIMER消息,而得到定时的效果(退出程序时别忘了调用和SetTimer配对使用的KillTimer函数)。二是利用GetTickCount函数可以返回自计算机启动后的时间,通过两次调用GetTickCount函数,然后控制它们的差值来取得定时效果,此方式跟第一种方式一样,精度也是毫秒级的。
  用这两种方式取得的定时效果虽然在许多场合已经满足实际的要求,但由于它们的精度只有毫秒级的,而且在要求定时时间间隔小时,实际定时误差大。下面介绍一种能取得高精度定时的方法。
  在一些计算机硬件系统中,包含有高精度运行计数器(high-resolution&& performance&& counter),利用它可以获得高精度定时间隔,其精度与CPU的时钟频率有关。采用这种方法的步骤如下:
  1、 首先调用QueryPerformanceFrequency函数取得高精度运行计数器的频率f。单位是每秒多少次(n/s),此数一般很大。
  2、 在需要定时的代码的两端分别调用QueryPerformanceCounter以取得高精度运行计数器的数值n1,n2。两次数值的差值通过f换算成时间间隔,t=(n2-n1)/f。
  下面举一个例子来演示这种方法的使用及它的精确度。
  在VC&& 6.0&& 下用MFC建立一个对话框工程,取名为HightTimer.在对话框面板中控件的布局如下图:
  其中包含两个静态文本框,两个编辑框和两个按纽。上面和下面位置的编辑框的ID分别为IDC_E_TEST和IDC_E_ACTUAL,通过MFC&& ClassWizard添加的成员变量也分别对应为DWORD&& m_dwTest和DWORD&& m_dwAct.&& “退出”按纽的ID为IDOK,“开始测试”按纽ID为IDC_B_TEST,用MFC&& ClassWizard添加此按纽的单击消息处理函数如下:
  void&& CHightTimerDlg::OnBTest()
  {
  //&& TODO:&& Add&& your&& control&& notification&& handler&& code&& here
  UpdateData(TRUE);&& //取输入的测试时间值到与编辑框相关联的成员变量m_dwTest中
  LARGE_INTEGER&&
  if(!QueryPerformanceFrequency(&& &frequence))&& //取高精度运行计数器的频率,若硬件不支持则返回FALSE
  MessageBox("Your&& computer&& hardware&& doesn't&& support&& the&& high-resolution&& performance&& counter",
  "Not&& Support",&& MB_ICONEXCLAMATION&& |&& MB_OK);
  LARGE_INTEGER&& test,&&
  test.QuadPart&& =&& frequence.QuadPart&& *&& m_dwTest&& /&& 1000000;&& //通过频率换算微秒数到对应的数量(与CPU时钟有关),1秒=1000000微秒
  ret&& =&& MySleep(&& test&& );&& //调用此函数开始延时,返回实际花销的数量
  m_dwAct&& =&& (DWORD)(1000000&& *&& ret.QuadPart&& /&& frequence.QuadPart&& );&& //换算到微秒数
  UpdateData(FALSE);&& //显示到对话框面板
  }
  其中上面调用的MySleep函数如下:
  LARGE_INTEGER&& CHightTimerDlg::MySleep(LARGE_INTEGER&& Interval)
  /////////////////////////////////////////////////////////////////////////////////////////////////////////////&
  //&& 功能:执行实际的延时功能&&&&
  //&& 参数:Interval&& 参数为需要执行的延时与时间有关的数量&&&&
  //&& 返回值:返回此函数执行后实际所用的时间有关的数量&&&&
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  LARGE_INTEGER&& privious,&& current,&& E
  QueryPerformanceCounter(&& &privious&& );
  current&& =&&
  while(&& current.QuadPart&& -&& privious.QuadPart&& 链接多媒体库winmm.lib,QueryPerformance*&& 函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于DOS平台下的高精度计时问题,可以参考《图形程序开发人员指南》,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而且函数调用的开销是最小的。&&
  3.具有和CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,可以直接计算出时间。这和QueryPerformanceCount不同,后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换算成时间。&&
  这个方法的缺点是:&&
  1.现有的C/C++编译器多数不直接支持使用RDTSC指令,需要用直接嵌入机器码的方式编程,比较麻烦。&&
  2.数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。这是这种方法高精度本身固有的矛盾。&&
  关于这个方法计时的最大长度,我们可以简单的用下列公式计算:&&
  自CPU上电以来的秒数&& =&& RDTSC读出的周期数&& /&& CPU主频速率(Hz)&&
  64位无符号整数所能表达的最大数字是1.8×10^19,在我的Celeron&& 800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。&&
  下面是几个小例子,简要比较了三种计时方法的用法与精度&&
  //Timer1.cpp&& 使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15&&
  //编译行:CL&& Timer1.cpp&& /link&& USER32.lib&&
  #include&&&&&
  #include&& "KTimer.h"&&
  main()&&
  unsigned&&&&
  KTimer&&&&
  timer.Start();&&
  Sleep(1000);&&
  t&& =&& timer.Stop();&&
  printf("Lasting&& Time:&& %d\n",t);&&
  //Timer2.cpp&& 使用了timeGetTime函数&&
  //需包含,但由于Windows头文件错综复杂的关系&&
  //简单包含比较偷懒:)&&
  //编译行:CL&& timer2.cpp&& /link&& winmm.lib&&&&
  #include&&&&&
  #include&&&&&
  main()&&
  DWORD&& t1,&& t2;&&
  t1&& =&& timeGetTime();&&
  Sleep(1000);&&
  t2&& =&& timeGetTime();&&
  printf("Begin&& Time:&& %u\n",&& t1);&&
  printf("End&& Time:&& %u\n",&& t2);&&
  printf("Lasting&& Time:&& %u\n",(t2-t1));&&
  //Timer3.cpp&& 使用了QueryPerformanceCounter函数&&
  //编译行:CL&& timer3.cpp&& /link&& KERNEl32.lib&&
  #include&&&&&
  #include&&&&&
  main()&&
  LARGE_INTEGER&& t1,&& t2,&&&&
  QueryPerformanceFrequency(&tc);&&
  printf("Frequency:&& %u\n",&& tc.QuadPart);&&
  QueryPerformanceCounter(&t1);&&
  Sleep(1000);&&
  QueryPerformanceCounter(&t2);&&
  printf("Begin&& Time:&& %u\n",&& t1.QuadPart);&&
  printf("End&& Time:&& %u\n",&& t2.QuadPart);&&
  printf("Lasting&& Time:&& %u\n",(&& t2.QuadPart-&& t1.QuadPart));&&
  ////////////////////////////////////////////////&&
  //以上三个示例程序都是测试1秒钟休眠所耗费的时间&&
  file://测/试环境:Celeron&& 800MHz&& /&& 256M&& SDRAM&&&&&&
  //&&&&&&&&&&&&&&&&&&&& Windows&& 2000&& Professional&& SP2&&
  //&&&&&&&&&&&&&&&&&&&& Microsoft&& Visual&& C++&& 6.0&& SP5&&
  ////////////////////////////////////////////////&&
  以下是Timer1的运行结果,使用的是高精度的RDTSC指令&&
  Lasting&& Time:&& &&
  以下是Timer2的运行结果,使用的是最粗糙的timeGetTime&& API&&
  Begin&& Time:&& &&
  End&& Time:&& &&
  Lasting&& Time:&& 1001&&
  以下是Timer3的运行结果,使用的是QueryPerformanceCount&& API&&
  Frequency:&& 3579545&&
  Begin&& Time:&& &&
  End&& Time:&& &&
  Lasting&& Time:&& 3569712
poav13poav
浏览: 6397 次
如果多个worker都在做同一个fuction的话,那job
This is sent to the ...
GRAB_JOB   向服务器请求一个的有效的队列任务。服务器 ...
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'关于函数QueryPerformanceFrequency()中的定时器
关于函数QueryPerformanceFrequency()中的定时器
编辑:www.fx114.net
本篇文章主要介绍了"关于函数QueryPerformanceFrequency()中的定时器
0yufuwan]",主要涉及到关于函数QueryPerformanceFrequency()中的定时器
0yufuwan]方面的内容,对于关于函数QueryPerformanceFrequency()中的定时器
0yufuwan]感兴趣的同学可以参考一下。
在一篇文章里看到:
对于精确度要求更高的定时操作,则应该使用
QueryPerformanceFrequency()和&QueryPerformanceCounter()函数。这两个函数
是VC提供的仅供Windows&95及其后续版本使用的精确时间函数,并要求计算机从硬
件上支持精确定时器。
那么,如何知道计算机从硬件上是否支持精确定时器呢????、
PS,有兴趣查看该文章的可以搜“&VC中基于&Windows&的精确定时”来阅读全文。上面提到的两个函数都是可以在MSDN里查到的,函数的说明也提到了需要硬件支持,但没有具体说明,哪位大虾能指点一二吗?新来的,没有积分送,难道因此就没人来回答吗?自己顶~~~~~~~~~~~~相信会有人来回答的~~~~~~~~~~~两个函数是Visual&C++提供并且仅供Windows&95及其后续版本使用,其精度与CPU的时钟频率有关
它们要求计算机从硬件上支持精确定时器。如果硬件不支持(高频率计数),即精度不够,会返回低精度的计数值
所以说不必自己判断是否硬件支持,根据返回值就能看出来
貌似在x86下都支持引用:
如果硬件不支持(高频率计数),即精度不够,会返回低精度的计数值&
所以说不必自己判断是否硬件支持,根据返回值就能看出来
能讲明白点吗?具体怎样根据返回值判断是否支持?我的cpu调用函数QueryPerformanceFrequency()的返回值是
1.4E-314,这个支持吗?好像这个数很小,感觉不正常呀,我的CPU是双核的~~~~哎,再问下,windows下能否利用上述函数实现1ms的精确定时???
自己顶上去~~~~~还是没人回答,UP一下吧~~~~~~一个测试定时的宏
RT_PREDEFINEVARIABLE()
RUNNINGTIME_BEGIN(&times&/*时间种类*/&)
&&&&call&functions&
&&&&elapsed&time.....
RUNNINGTIME_END()
#include&"stdafx.h"
#include&&windows.h&
const&int&RT_SECONDS&=&1000000&;
const&int&RT_MILLISECONDS&=&1000&;
const&int&RT_MICROSECONDS&=&1&;
#define&RT_PREDEFINEVARIABLE()&\
&&&&&&&&&&&&&LARGE_INTEGER&m_liPerfFreq={0};&\
&&&&&&&&&&&&&LARGE_INTEGER&m_liPerfStart={0};&\
&&&&&&&&&&&&&LARGE_INTEGER&liPerfNow={0};&\
&&&&&&&&&&&&&int&selectedtime&=&0&;&\
&&&&&&&&&&&&&CHAR&sSelectedTime[16]&;
#define&RUNNINGTIME_BEGIN(&times&)&\
&&&&&&&&&&&&&selectedtime&=&times&;&\
&&&&&&&&&&&&&if(&selectedtime&==&RT_SECONDS&)&strcpy(&sSelectedTime,&"Seconds"&);&\
&&&&&&&&&&&&&if(&selectedtime&==&RT_MILLISECONDS&)&strcpy(&sSelectedTime,&"MilliSeconds"&);&\
&&&&&&&&&&&&&if(&selectedtime&==&RT_MICROSECONDS&)&strcpy(&sSelectedTime,&"MicroSeconds"&);&\
&&&&&&&&&&&&&QueryPerformanceFrequency(&m_liPerfFreq);&\
&&&&&&&&&&&&&QueryPerformanceCounter&&(&m_liPerfStart)&;&
#define&RUNNINGTIME_END()&\
&&&&&&&&&&&&&QueryPerformanceCounter&&(&liPerfNow)&;&\
&&&&&&&&&&&&&printf("Function&spends:&%u.%.6u&%s\n\n",&\
&&&&&&&&&&&&&(unsigned&long)((liPerfNow.QuadPart-m_liPerfStart.QuadPart)*1000000/m_liPerfFreq.QuadPart)/selectedtime,&\
&&&&&&&&&&&&&(unsigned&long)((liPerfNow.QuadPart-m_liPerfStart.QuadPart)*1000000/m_liPerfFreq.QuadPart)%selectedtime,&\
&&&&&&&&&&&&&&&&&&&&&&&&&sSelectedTime&);&汗,实在是看不懂,能解释一二么????
一、不得利用本站危害国家安全、泄露国家秘密,不得侵犯国家社会集体的和公民的合法权益,不得利用本站制作、复制和传播不法有害信息!
二、互相尊重,对自己的言论和行为负责。
本文标题:
本页链接:温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!&&|&&
LOFTER精选
网易考拉推荐
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
上一次wang老大告诉我可以用奔腾指令RDTSC获取高精度计时值, 一直没空研究,今天正好查了相关资料,觉得太好用了,可以把它写成一个内联函数以便程序应用。//RDTSC返回的是CPU上电以来所经过的时钟周期数,存在EDX:EAX中。inline unsigned __int64 GetCycleCount(){__asm _emit 0x0F__asm _emit 0x31 //RDTSC的机器代码0F 31}我以前一直都是用8253的计时值来高精度测时,但也只能达到us级的精度(加上I/O指令慢,实际最高测量精度约5us)。我常常需要us级的时间测量或延迟,这给了我个新的选择。此外用它做随机数种子也非常不错。当然唯一的缺点就是降低了移植性,所以要根据自己的需求技巧性地选用,比如封装在一个类里面。通常场合如果不需要这么高测量精度的,还是慎用为是。和其他windows时间函数比较,它的精度可达纳秒级(ns),而且简单。详细比较,请参考文章 /Control/CPUTime.htm
非常不幸的是,CPU的时钟频率虽然很高,但受制于主板的时钟发生器,而这个发生器的误差实在大得惊人,一般每几分钟就误差一秒。它是“精确计时”的灾星!---------------------------------------------------The grass survives the hill through itsresurrections from countless deaths.草儿从无数死亡中复活,所以山死后它还活着
时基误差大小和时钟源有关,一般振荡电路都是用石英晶体控制频率,每个石英晶体都有自己固定的谐振频率,如果没有经过微调,有些误差可能较大(一般一天几秒,不会你说的那么大),经过微调每天可以低于1s,甚至更低。但是即便误差再大,石英的稳定性仍然信得过,而我们要的就是稳定性(见下面分析)。晶体的品质有好坏,其精度和稳定性可以差几个数量级,但对我们的应用仍然完全足够。通常主板上被我们用作计时的时钟源有,系统时钟、实时钟、CPU时钟。系统时钟是PC结构最早支持的,晶体频率是14.318Mhz, 由8253定时/计数器(CTC)分频后提供给软件,软件可读取的最小的时钟为1.193MHz,时钟周期为0.84us,8253的CH0经过65536分频后产生18.2Hz的系统时钟中断(IRQ0).实时钟(RTC)是后来AT机开始引入用来记录真实时间的部件,内部记录年月日时分秒、闹钟等,还可以产生1KHz的中断时钟信号(IRQ8)。它的晶体频率是32768kHz.CPU时钟从XT的4.77Mhz到AT的8Mhz直到现在的1GHz以上,不是固定的,但是稳定性一样很好,而且凭经验, 精度和稳定性应该更好,而RTC的晶体反而应该是最便宜,精度稳定性也最差。说明一下,实际上CPU时钟误差有多大对我们测时毫无影响,因为CPU的时钟对软件来说本来就是未知的,应用RDTSC测时,首先必须依靠CTC或RTC作为时基,把CPU时钟频率测出来保存起来,再以此为基准去换算RDTSC读数为实际时间,所以真正精度就取决于时基CTC或RTC了,跟CPU时钟没有关系,只要它稳定就行。据说VC的QueryPerformanceCounter和QueryPerformanceFrequency就是基于该指令实现的。可是我又看到另外的文章说QueryPerformanceFrequency()返回值是1.193MHz,可见仍然是利用CTC实现的。到底是多少?有VC的朋友自己测一下就知道,这个跟系统实现有关。虽说跟平台相关,实际上不过是要求奔腾兼容CPU即可,这是目前普遍的开发平台。再把它做成自己的类, 这样Linux、Windows、DOS等都可以使用,而且利用内联函数,开销非常低。比如可以利用它测量各个指令的指令周期等等。另外要注意一点就是,某些笔记本可能会动态改变CPU时钟(节电模式), 如果是这种情况,那么必须有个进程动态调整时基,否则可能存在问题(这个我未印证).&肥猫& 写入邮件 news:...&& 非常不幸的是,CPU的时钟频率虽然很高,但受制于主板的时钟发生器,而这个发生& 器的误差实在大得惊人,一般每几分钟就误差一秒。& 它是“精确计时”的灾星!&& ---------------------------------------------------& The grass survives the hill through its& resurrections from countless deaths.& 草儿从无数死亡中复活,所以山死后它还活着
我平时写了一个性能测试类,就是用这个东西的,现在贡献出来,代码写得有点乱,请大家指教说明:文件最下面有一个使用的示例代码需要注意的是如果是在非控制台下面使用xn类,则需要在#include本文件之前#define _CONSOLE_PRJ_ ,这样所有的输出信息将会在debug窗口中输出只在win32+VC6下做过测试#ifndef _LS_DBG_#define _LS_DBG_#include "windows.h"#include &iostream&/********************************************************************命名空间: ls_dbgcreated:
16:30filename: ls_dbg.hauthor: 李?呈
或者 purpose: 跟踪并且性能测试,具体说明见“xn类说明”,使用方式见“示例代码”平台: Win32备注: 如果需要将性能测试结果输出到控制台, 则需要在#include本文件之前 #define _CONSOLE_PRJ_ ,否则测试结果信息会输出到调试窗口内容: 1. _trace()函数: void _trace(char*fmt,...)2. xn类: class xn待完善的功能: 加入内存泄漏的检测代码其他: 如果代码有什么需要改善之处,请给我发电子邮件讨论邮件地址为:
或者 *********************************************************************/namespace ls_dbg{//_trace()函数说明://1.功能:完成MFC中TRACE宏一样的功能//2.如果项目没有定义_CONSOLE_PRJ_宏(说明是一个控制台项目),// 则使用此_trace函数输出xn类的跟踪信息否则就直接使用cout// 否则直接用cout输出跟踪信息,因为默认情况下项目不会定义// _CONSOLE_PRJ_宏,所以默认情况会用本_trace函数输出跟踪信息void _trace(char*fmt,...){char out[256];va_va_start(body,fmt);vsprintf(out,fmt,body);va_end(body);OutputDebugString(out);}//xn类说明://功能:跟踪一段变量生命周期的进入和退出情况,如果需要,可以显示时间//注意:// 1) 本跟踪及性能测试类如果用来测试cpu频率,只能检测4.3G以内的cpu,// 否则unsigned会溢出(这个4.3G的数值是我自己大致出来的,可能有误)// 2) 使用了intel的汇编指令,可能在非intel平台上无法运行//程序机制:使用构造函数和析构函数//构造函数参数说明:// 1: xn(char* name, bool dispSwitch=false, unsigned cpufreq=0)// xn(被跟踪模块名称,是否显示此模块执行时间,显式指定cpu频率)// 2: xn(bool dispSwitch=false, unsigned cpufreq=0), 不指定被跟踪模块名称,其他参数含义与上面类似//构造函数其他说明:// 1、指定被跟踪模块名称将会在跟踪记录输出时显示被跟踪模块// 2、显式指定cpu频率是为了提高跟踪效率, 否则要花费一秒钟时间检测本地cpu频率//本文件底部有示例代码class xn{char* //传入的性能测试也就是被跟踪的模块名称char* //单位mhzunsigned __int64 m_bool dispSpendT //true:显示花费的时间,默认为falseu //注意:单位是hz而不是mhzpublic: unsigned __int64 GetCycleCount( void){_asm _emit 0x0F_asm _emit 0x31}void Start(void){m_startcycle = GetCycleCount();}unsigned __int64 Stop(void) //返回的是自从上一次Start()函数被调用以后所经历的cpu周期数{ return GetCycleCount()-m_//-m_ //注意,这个Stop和//%bij%\jis计算机笔记\source\jis计时器\利用cpu频率计时 中的Stop//函数不同,原来是 return GetCycleCount()-m_startcycle-m_}void SetCpuSpeed(unsigned newfreq=0) //确定一秒钟运行了多少周期{if(newfreq){cpufrequency=}unsigned starttest=GetCycleCount();Sleep(1000); unsigned endtest=GetCycleCount();cpufrequency=endtest-}unsigned GetCpuSpeed(){if(!cpufrequency)SetCpuSpeed(); //注意:单位是hz而不是mhz}char* GetCpuSpeedString(void){if(!cpufrequency)SetCpuSpeed();cpuspeed=new char[24];sprintf(cpuspeed,"%d.%d mhz",(unsigned)cpufrequency/1000000,(unsigned)cpufrequency%1000000);}public://注意:cpufreq单位是hz,而不是mhz,所以如果是733mhz的机器要填入xn(char* name, bool dispSwitch=false, unsigned cpufreq=0):xnname(name),dispSpendTime(dispSwitch),cpufrequency(cpufreq),cpuspeed(0){// Start();if(name){#ifdef _CONSOLE_PRJ_cout&&"+& START trace: "&&xnname&&#else_trace("+&START trace: %s\n",xnname);#endif}// m_overhead=Stop();Start();}//注意:cpufreq单位是hz,而不是mhz,所以如果是733mhz的机器要填入xn(bool dispSwitch=false,unsigned cpufreq=0):xnname(0),dispSpendTime(dispSwitch),cpufrequency(cpufreq),cpuspeed(0){#ifdef _CONSOLE_PRJ_ cout&&"+& START trace\n"; #else_trace("+& START trace\n");#endifStart();}~xn(){unsigned spendcycle=(unsigned)Stop();if(xnname){#ifdef _CONSOLE_PRJ_cout&&"+& END trace: "&&xnname&&cout&&" |--spend cycle: "&&(unsigned)spendcycle&&if(dispSpendTime) //判断是否显示执行时间,单位:秒{if(cpufrequency)cout&&" |--spend time: "&&(float)((float)spendcycle/(float)cpufrequency)&&" s"&&else{cout&&" |--spend time: "&&(float)((float)spendcycle)/((float)GetCpuSpeed())&&" s"&&}}#else_trace("+& END trace: %s\n",xnname);_trace(" |--spend cycle: %d\n",(unsigned)spendcycle);if(dispSpendTime){if(cpufrequency)_trace(" |--spend time: %f s\n",(float)((float)spendcycle/(float)cpufrequency));else{_trace(" |--spend time: %f s\n",(float)((float)spendcycle)/((float)GetCpuSpeed()));}}#endif}//if(xnname)else{#ifdef _CONSOLE_PRJ_cout&&"+& END trace"&&cout&&" |--spend cycle: "&&(unsigned)spendcycle&&if(cpufrequency)cout&&" |--spend time: "&&(float)((float)spendcycle/(float)cpufrequency)&&" s"&&else{cout&&" |--spend time: "&&(float)((float)spendcycle)/((float)GetCpuSpeed())&&" s"&&}#else_trace("+& END trace\n");_trace(" |--spend cycle: %d \n",(unsigned)spendcycle);if(cpufrequency)_trace(" |--spend time: %f s\n",(float)((float)spendcycle/(float)cpufrequency));else{_trace(" |--spend time: %f s",(float)((float)spendcycle)/((float)GetCpuSpeed()));}#endif}//elseif(!cpuspeed)}//end xn::~xn()};//end class xn}//end namespace ls_dbg#endif //#define _LS_DBG_//示例代码//int main(int argc, char* argv[])//{// xn mainxn("main",true,); //显式指定CPU速度// xn mainxn("main",true); //不显示指定CPU速度,对象自己测试该速度值// cout&&"cpu speed="&&mainxn.GetCpuSpeed()&&// printf("调试类测试!\n");// {// xn forxn("for",true,mainxn.GetCpuSpeed());// for(int i=0;i&20;i++)// cout&&"i="&&i&&// Sleep(2000);// }// return 0;//}
Intel处理器上的RDTSC 提供基于处理器时钟的精确定时,可以达到1 纳秒精度
Intel的文档说明
RDTSC—Read Time-Stamp Counter
Description
Loads the current value of the processor’s time-stamp counter (a 64-bit MSR) into
the EDX:EAX registers. The EDX register is loaded with the high-order 32 bits of the
MSR and the EAX register is loaded with the low-order 32 bits. (On processors that
support the Intel 64 architecture, the high-order 32 bits of each of RAX and RDX are
The processor monotonically increments the time-stamp counter MSR every clock
cycle and resets it to 0 whenever the processor is reset. See “Time Stamp Counter”
in Chapter 18 of the Intel& 64 and IA-32 Architectures Software Developer’s Manual,
Volume 3B, for specific details of the time stamp counter behavior.
When in protected or virtual 8086 mode, the time stamp disable (TSD) flag in
register CR4 restricts the use of the RDTSC instruction as follows. When the TSD flag
is clear, the RDTSC instruction can be executed at when the flag
is set, the instruction can only be executed at privilege level 0. (When in real-address
mode, the RDTSC instruction is always enabled.)
The time-stamp counter can also be read with the RDMSR instruction, when
executing at privilege level 0.
The RDTSC instruction is not a serializing instruction. Thus, it does not necessarily
wait until all previous instructions have been executed before reading the counter.
Similarly, subsequent instructions may begin execution before the read operation is
performed.
This instruction was introduced by the Pentium processor.
See “Changes to Instruction Behavior in VMX Non-Root Operation” in Chapter 21 of
the Intel& 64 and IA-32 Architectures Software Developer’s Manual, Volume 3B, for
more information about the behavior of this instruction in VMX non-root operation.
IF (CR4.TSD = 0) or (CPL = 0) or (CR0.PE = 0)
THEN EDX:EAX ← TimeStampC
ELSE (* CR4.TSD = 1 and (CPL = 1, 2, or 3) and CR0.PE = 1 *)
Opcode Instruction 64-Bit
Description
0F 31 RDTSC Valid Valid Read time-stamp counter into
4-252 Vol. 2B RDTSC—Read Time-Stamp Counter
INSTRUCTION SET REFERENCE, N-Z
Flags Affected
Protected Mode Exceptions
#GP(0) If the TSD flag in register CR4 is set and the CPL is greater than
#UD If the LOCK prefix is used.
Real-Address Mode Exceptions
#UD If the LOCK prefix is used.
Virtual-8086 Mode Exceptions
#GP(0) If the TSD flag in register CR4 is set.
#UD If the LOCK prefix is used.
Compatibility Mode Exceptions
Same exceptions as in protected mode.
64-Bit Mode Exceptions
Same exceptions as in protected mode.
===GetCycleCount 函数和注释是网上抄下来的 ,vs2003里面已经可以认出RDTSC指令了=========
#include&iostream&&&
using&& namespace&&
//#include&stdio.h&
//#include&stdlib.h&
//本文要介绍的,是另一种直接利用Pentium CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书,第15页-17页,有兴趣的读者可以直接参考该书。关于 RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。
//在Intel Pentium以上级别的CPU中,有一个称为“时间戳(Time Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。
//在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:
inline unsigned __int64 GetCycleCount()
__asm RDTSC
//但是不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:
//inline unsigned __int64 GetCycleCount()
//__asm _emit 0x0F
//__asm _emit 0x31
inline unsigned int dddd()
__asm RDTSC
__asm mov ebx,eax
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
//__asm test ecx,5
__asm mov ecx,0
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm cmp ecx,5
__asm RDTSC
__asm sub eax ,ebx
int main()
int i = (dddd() + dddd()+dddd()+dddd()+dddd()+dddd()+dddd()+dddd()+dddd()+dddd())/10;
cout && "i=" && i &&
&& cout&& "good"&&
if (i & 0)
cout&& "bad"&&
unsigned long t1; unsigned long t2; unsigned long t3;
t1 = (unsigned long)GetCycleCount();
bool flag =
&& t2 = (unsigned long)GetCycleCount();
&& cout&& "good"&&
cout && "t2-t1=" &&t2-t1 &&
t2 = (unsigned long)GetCycleCount();
if (flag ==true)
&& t3 = (unsigned long)GetCycleCount();
&& cout&& "bad"&&
cout && "t3-t2=" &&t3-t2 &&
cout &&"bool ="&& sizeof (bool)&& "字节" &&
阅读(1006)|
用微信&&“扫一扫”
将文章分享到朋友圈。
用易信&&“扫一扫”
将文章分享到朋友圈。
历史上的今天
loftPermalink:'',
id:'fks_087067',
blogTitle:'RDTSC 汇编指令提供的精确定时功能',
blogAbstract:'/*----------------------------------------------------------------------------& | gcc IA32 specific macros/functions&*---------------------------------------------------------------------------*/#&&& if defined(ARCH_IS_IA32) || defined(ARCH_IS_X86_64)#&&&&&&& define BSWAP(a) __asm__ ( \"bswapl %0\\n\" : \"=r\" (a) : \"0\" (a) );',
blogTag:'',
blogUrl:'blog/static/',
isPublished:1,
istop:false,
modifyTime:2,
publishTime:3,
permalink:'blog/static/',
commentCount:0,
mainCommentCount:0,
recommendCount:0,
bsrk:-100,
publisherId:0,
recomBlogHome:false,
currentRecomBlog:false,
attachmentsFileIds:[],
groupInfo:{},
friendstatus:'none',
followstatus:'unFollow',
pubSucc:'',
visitorProvince:'',
visitorCity:'',
visitorNewUser:false,
postAddInfo:{},
mset:'000',
remindgoodnightblog:false,
isBlackVisitor:false,
isShowYodaoAd:false,
hostIntro:'',
hmcon:'0',
selfRecomBlogCount:'0',
lofter_single:''
{list a as x}
{if x.moveFrom=='wap'}
{elseif x.moveFrom=='iphone'}
{elseif x.moveFrom=='android'}
{elseif x.moveFrom=='mobile'}
${a.selfIntro|escape}{if great260}${suplement}{/if}
{list a as x}
推荐过这篇日志的人:
{list a as x}
{if !!b&&b.length>0}
他们还推荐了:
{list b as y}
转载记录:
{list d as x}
{list a as x}
{list a as x}
{list a as x}
{list a as x}
{if x_index>4}{break}{/if}
${fn2(x.publishTime,'yyyy-MM-dd HH:mm:ss')}
{list a as x}
{if !!(blogDetail.preBlogPermalink)}
{if !!(blogDetail.nextBlogPermalink)}
{list a as x}
{if defined('newslist')&&newslist.length>0}
{list newslist as x}
{if x_index>7}{break}{/if}
{list a as x}
{var first_option =}
{list x.voteDetailList as voteToOption}
{if voteToOption==1}
{if first_option==false},{/if}&&“${b[voteToOption_index]}”&&
{if (x.role!="-1") },“我是${c[x.role]}”&&{/if}
&&&&&&&&${fn1(x.voteTime)}
{if x.userName==''}{/if}
网易公司版权所有&&
{list x.l as y}
{if defined('wl')}
{list wl as x}{/list}

我要回帖

更多关于 返回值是指针的函数 的文章

 

随机推荐