C ++ / POSIX如何获得毫秒时间戳最有效的方法?

我为i2c总线操作使用了一个开源库。 这个库经常使用一个函数来获得毫秒级分辨率的实际时间戳

示例呼叫:

nowtime = timer_nowtime(); while ((i2c_CheckBit(dev) == true) && ((timer_nowtime() - nowtime) < I2C_TIMEOUT)); 

使用这个i2c库的应用程序使用了大量的CPU容量。 我发现,运行的程序最多的时间是调用函数timer_nowtime()

原来的function:

 unsigned long timer_nowtime(void) { static bool usetimer = false; static unsigned long long inittime; struct tms cputime; if (usetimer == false) { inittime = (unsigned long long)times(&cputime); usetimer = true; } return (unsigned long)((times(&cputime) - inittime)*1000UL/sysconf(_SC_CLK_TCK)); } 

我现在的目标是提高这个function的效率。 我这样试了:

 struct timespec systemtime; clock_gettime(CLOCK_REALTIME, &systemtime); //convert the to milliseconds timestamp // incorrect way, because (1 / 1000000UL) always returns 0 -> thanks Pace //return (unsigned long) ( (systemtime.tv_sec * 1000UL) + (systemtime.tv_nsec // * (1 / 1000000UL))); return (unsigned long) ((systemtime.tv_sec * 1000UL) + (systemtime.tv_nsec / 1000000UL)); 

不幸的是,我不能声明这个函数内联 (不知道为什么)。

用msparsing获得实际时间戳的方法更有效率? 我确信有一个更多的per-formant的方式来这样做。 有什么build议么?

谢谢。

清楚的是,您的示例调用在timer_nowtime()函数中使用了大部分CPU时间。 你在轮询,循环吃你的CPU时间。 你可以用一个更好的选择交换定时器函数,所以你可以实现更多的循环迭代,但是它仍然会使用该函数中的大部分CPU时间! 通过改变你的定时器功能,你不会达到更少的CPU时间!

你可以改变你的循环,并引入等待时间 – 但只有在你的应用程序中有意义,例如:

 start = timer_nowtime(); while( i2c_CheckBit(dev) ) { now = timer_nowtime(); diff = now - start; if( diff < I2C_TIMEOUT ) break; else if( diff > SOME_TRESHOLD ) usleep( 1000*std::max(1,I2C_TIMEOUT-diff-SOME_SMALL_NUMBER_1_TO_10_MAYBE) ); } 

定时器:我认为gettimeofday()是一个很好的决定,它具有很高的精度,并且可以在大多数(所有?)Unices中使用。

请注意,你的两个例子是不相同的; 次(2)测量CPU时间消耗,而clock_gettime(CLOCK_REALTIME,…)测量挂钟时间。

也就是说,wallclock定时器(如clock_gettime或更早的gettimeofday)通常比CPU(比如times()或getrusage())快得多。

而且,正如已经指出的那样,你的定时功能占用了大量的CPU时间,因为除了轮询它之外别无它法。 如果这是一个问题,等待一点,例如通过调用nanosleep()或clock_nanosleep()。

我认为你最好的选择是使用clock_gettime(),但是CLOCK_MONOTONIC而不是CLOCK_REALTIME。

我一直很高兴在Linux上:

 inline double getFractionalSeconds(void) { struct timeval tv; // see gettimeofday(2) gettimeofday(&tv, NULL); double t = (double) tv.tv_sec + (double) 1e-6 * tv.tv_usec; // return seconds.microseconds since epoch return(t); } 

如果您的程序仅在最近的英特尔/ AMD处理器上执行,但不是太近(时钟调节处理不好), RDTSC汇编指令是获取时间戳的最佳方法。 分辨率接近处理器的实际时钟,与系统无关(这意味着它也会受到中断的影响,也不能让你的蛋糕吃掉)。

这个页面在C中有一个例子

如果您在英特尔上运行,则可以尝试以下代码

 unsigned long long int rdtsc(void) { unsigned long long int x; unsigned a, d; __asm__ volatile("rdtsc" : "=a" (a), "=d" (d)); return ((unsigned long long)a) | (((unsigned long long)d) << 32);; }