分类:
2010-06-21 09:26:14
使用C语言进行计时,在用户空间中可以使用C语言函数gettimeofday 得到时间,它的调用格式是:
#include
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv , const struct timezone *tz);
结构timeval的定义为:
strut timeval {long tv_sec; /* 秒数 */long tv_usec; /* 微秒数 */};
可以看出,使用这种方式计时,精度可达微秒,也就是10-6秒。进行计时的时候,我们需要前后调用两次gettimeofday,然后计算中间的差值:
gettimeofday( &start, NULL );
foo();
gettimeofday( &end, NULL );
timeuse = 1000000 * ( end.tv_sec - start.tv_sec ) + end.tv_usec - start.tv_usec;
timeuse /= 1000000;
2、自己写的在linux基于qt4.6的us级的计时程序:
#include
#include
#include
#include
void caculate()
{
for(int i=0;i<32323;i++)
{
for(int j=0;j<32323;j++)
;
}
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget *w = new QWidget;
QLabel *label1,*label2,*label3;
struct timeval start;
struct timeval end;
quint64 timestart,timeend,timeuse;
//获得CPU计时器的时钟频率
gettimeofday(&start,NULL);//开始计时
caculate(); //待测试的计算函数等
gettimeofday(&end,NULL); //终止计时
timestart = 1000000*start.tv_sec+start.tv_usec;
timeend = 1000000*end.tv_sec+end.tv_usec;
timeuse = timeend-timestart;
label1 = new QLabel("Start Time:"+QString::number(timestart,10)+" us",w);
label1->setGeometry(10,10,400,30);
label2 = new QLabel("End Time:"+QString::number(timeend,10)+" us",w);
label2->setGeometry(10,50,400,30);
label3 = new QLabel("Use Time:"+QString::number(timeuse,10)+" us",w);
label3->setGeometry(10,90,400,30);
w->setMinimumSize(400,200);
w->setMaximumSize(400,200);
w->show();
return a.exec();
}
3、另外附上其它的基本知识:
最小到秒的时间的获取
int time(char cnt)
{
time_t t; //实例化time_t结构
struct tm *timenow1; //实例化tm结构指针
struct tm *timenow2; //实例化tm结构指针
time(&t);//time函数读取现在的时间(国际标准时间非北京时间),然后传值给t
timenow1=localtime(&t); //localtime函数把从time取得的时间t换算成你电脑中的时间(就是你设置的地区)
printf("the current time1 is: %02d:%02d:%02d\n",timenow1->tm_hour,timenow1->tm_min,timenow1- >tm_sec);
printf("Local time1 is %s\n",asctime(timenow1)); //上句中asctime函数把时间转换成字符,通过printf()函数输出
time(&t);
timenow2=localtime(&t);
printf("the current time2 is: %02d:%02d:%02d\n",timenow2->tm_hour,timenow2->tm_min,timenow1->tm_sec);
printf("Local time2 is %s\n",asctime(timenow2));
if((timenow2->tm_hour==timenow1->tm_hour) && (timenow2->tm_min==timenow1->tm_min))
{
n=timenow2->tm_sec-timenow2->tm_sec;
printf("n is %d\n",n);//秒
}
//注:如果想获得国际标准时间,将localtime换成gmtime函数
//注:time_t是一个在time.h中定义好的结构体。而tm结构体的原形如下:
/*
struct tm //最小到秒,#include
{
int tm_sec;//seconds 0-61
int tm_min;//minutes 1-59
int tm_hour;//hours 0-23
int tm_mday;//day of the month 1-31
int tm_mon;//months since jan 0-11
int tm_year;//years from 1900
int tm_wday;//days since Sunday, 0-6
int tm_yday;//days since Jan 1, 0-365
int tm_isdst;//Daylight Saving time indicator
};
*/
}
纳秒级计时
函数原型:int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
其中参数timespec定义是:
struct timespec
{
time_t tv_sec; /* seconds * /
long tv_nsec; /* nanoseconds * /
}
实际应用(部分,不完整):
struct timesepc req;
struct timespec rem;
int ret;
req.tv_sec = 2; //这就表示2秒
req.tv_nsec = 0;
ret = nanosleep(&req, &rem);
if (ret < 0)
{
//....
}
用rdrtc实现linux下的精确计时
在linux开发版最长问到的问题之一就是在linux下如何得到更精确的计时。其实有很多办法,比如以前就有人用select。不过现在有更精确 的实时时钟可以用,这就是用CLOCK_PROCESS_CPUTIME_ID做参数通过timer_create来创建timer。通过 clock_getres可以得到系统的精度。
实际上,上述方法底层用的就是CPU的rdtsc指令。 在linux下,可以用到CPU的rdtsc指令(当然,windows下也是这样。现在的CPU一般都支持这个指令)来得到一个CPU的时间戳 (Time Stamp),这个值是每个指令周期都增加的,再根据CPU的频率就可以计算出时间来。用这种方式,对于频率高的CPU,甚至可以实现纳秒级的时间控制。 不过据说因为精度太高,这种方式数据抖动比较厉害,每次结果都不一样,经常有几百甚至上千的差距。不过在我的实验中误差并没有这么大,上下在1%左右,不 过如果你的要求高的话,这1%也是很厉害的。不过sleep调用也是会有误差的,这里就不去研究了。
下面是源码:
#include
int get_rdtsc() {
asm("rdtsc");
}
int main() {
int i;
for(i=0;i<10;i++) {
int t1 = get_rdtsc();
sleep(1);
int t2 = get_rdtsc();
printf("t2 - t1 = %ld (%ldMHZ) ", t2 - t1, (t2-t1)/1000000);
}
}
我的实验环境:Intel E6320/2G,使用VMWare虚拟机,系统是centos5-x86。下面是输出结果。
t2 - t1 = 1865320163 (1865MHZ)
t2 - t1 = 1865996702 (1865MHZ)
t2 - t1 = 1862758710 (1862MHZ)
t2 - t1 = 1865247214 (1865MHZ)
t2 - t1 = 1863456686 (1863MHZ)
t2 - t1 = 1865427930 (1865MHZ)
t2 - t1 = 1865423429 (1865MHZ)
t2 - t1 = 1863616999 (1863MHZ)
t2 - t1 = 1865105795 (1865MHZ)
t2 - t1 = 1867224090 (1867MHZ)