加入收藏 | 设为首页 | 会员中心 | 我要投稿 济南站长网 (https://www.0531zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

浅析Linux中的时间编程和实现原理(一) Linux应用层的时间编程

发布时间:2016-09-07 14:55:31 所属栏目:Linux 来源:站长网
导读:引子 我们都生活在时间中,但却无法去思考它。什么是时间呢?似乎这是一个永远也不能被回答的问题。然而作为一个程序员,在工作中,总有那么几次我必须思考什么

时间的测量

有时候我们要计算某段程序执行的时间,比如需要对算法进行时间分析。基本的实现思路为在被测试代码的开始和结束的地方获取当时时间,相减后得到相对值,即所需要的统计时间。为了实现高精度的时间测量,必须使用高精度的时间获取方式,一般有两种方法:

系统调用 gettimeofday

汇编指令 RDTSC。

gettimeofday

可以使用 gettimeofday() 函数进行时间测量,其精度在 us 级别,可以用来做一般的时间分析。

gettimeofday() 将时间保存在结构 tv 之中。gettimeofday() 的第二个参数代表时区,在 Linux 中已经废弃不用,只能用 NULL 传入。一个典型的例子程序如下:

清单 6,gettimeofday 例子程序

void function() 
{ 
 unsigned int i,j; 
 double y; 
 for(i=0;i<1000;i++) 
 for(j=0;j<1000;j++) 
 y=sin((double)i); //耗时操作
} 
      
main() 
{ 
 struct timeval tpstart,tpend; 
 float timeuse; 
      
 gettimeofday(&tpstart,NULL); //记录开始时间戳
 function(); 
 gettimeofday(&tpend,NULL); //记录结束时间戳
 timeuse = 1000000*(tpend.tv_sec-tpstart.tv_sec)+ 
tpend.tv_usec-tpstart.tv_usec; //计算差值
 timeuse /= 1000000; 
 printf("Used Time:%fn",timeuse); 
 exit(0); 
}

这个程序输出函数的执行时间,我们可以使用这个来进行系统性能的测试,或者是函数算法的效率分析。在我个人机器上的输出结果是:Used Time:0.556070

RDTSC

gettimeofday() 是一个系统调用,在某些场合下频繁调用它是不合适的。比如性能要求很高的代码段内。因为 gettimeofday() 需要用户态/内核态切换,开销较大。Intel X86 处理器提供了 TSC 硬件,并且可以用非特权指令 rdtsc 来读取该硬件的时间值,这就避免了过度的内核用户态切换。

如何使用 RDTSC

参考下面的例子代码,采用 GCC 的汇编扩展,定义 rdtsc 的函数,它返回当前时间戳。

#define rdtsc(low,high) __asm__

__volatile__("rdtsc" : "=a" (low), "=d" (high))

在 C 代码中使用 rdtsc 十分简单。比如:

清单 7,RDTSC 例子程序

unsigned long long get_cycles()
{
    unsigned low, high;
    unsigned long long val;
    rdtsc(low,high);
    val = high;
val = (val << 32) | low; //将 low 和 high 合成一个 64 位值
    return val;
}
      
double get_cpu_mhz(void)
{
    FILE* f;
    char buf[256];
    double mhz = 0.0;
      
f = fopen("/proc/cpuinfo","r"); //打开 proc/cpuinfo 文件
    if (!f)
        return 0.0;
    while(fgets(buf, sizeof(buf), f)) {
        double m;
        int rc;
rc = sscanf(buf, "cpu MHz : %lf", &m); //读取 cpu MHz
        if (mhz == 0.0) {
            mhz = m;
            break;
        }
    }
    fclose(f);
return mhz; //返回 HZ 值
}
      
int main()
{
    double mhz;
    mhz = get_cpu_mhz();
    cycles_t c1, c2;
      
    for(;;)
    {
        c1 = get_cycles(); 
        sleep(1);
        c2 = get_cycles();
 //c2 和 c1 的差值应该为 1000000us,即 1 秒
        printf("1 sec = %g usecn", (c2 - c1) / mhz); 
    }
}

函数 get_cycles 将返回 64 位整数,代表当前时间,单位是 CPU 的 cycle 数。函数 get_cpu_mhz 获得当前 CPU 的工作频率。用两个 CPU cycle 的差值除以 CPU 频率,就是微妙。

但 RDTSC 只能在 IA 系列处理器上使用。而且由于处理器的乱序执行,RDTSC 有些情况下并不准确,在 SMP 下使用 RDTSC 也有一定的问题。但这些问题只有在需要极高时间精度的情况下才会出现,对于一般的时间测量要求,采用 RDTSC 是一个可以考虑的选择。

(编辑:济南站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读