linux - clock_gettime() 是否适合亚微秒计时?

标签 linux performance ubuntu profiling

我需要一个高分辨率计时器,用于我们应用程序的 Linux 构建中的嵌入式分析器。我们的分析器测量的范围小到单个函数,因此它需要优于 25 纳秒的计时器精度。

之前我们的实现使用内联汇编和rdtsc操作直接从CPU查询高频定时器,但是this is problematic和需要频繁的重新校准。

所以我尝试使用 clock_gettime 函数来查询 CLOCK_PROCESS_CPUTIME_ID。文档声称这给了我纳秒级的计时,但我发现单次调用 clock_gettime() 的开销超过 250ns。这使得不可能为 100 纳秒长的事件计时,并且在定时器功能上拥有如此高的开销会严重拖累应用程序性能,扭曲配置文件超出值(value)。 (我们每秒有数十万个分析节点。)

有没有一种调用 clock_gettime() 的方法开销小于 ¼μs? 或者有没有其他方法可以可靠地获取 <25ns 的时间戳计数器高架?还是我坚持使用 rdtsc

下面是我用来计时的代码clock_gettime()

// calls gettimeofday() to return wall-clock time in seconds:
extern double Get_FloatTime();
enum { TESTRUNS = 1024*1024*4 };

// time the high-frequency timer against the wall clock
{
    double fa = Get_FloatTime();
    timespec spec; 
    clock_getres( CLOCK_PROCESS_CPUTIME_ID, &spec );
    printf("CLOCK_PROCESS_CPUTIME_ID resolution: %ld sec %ld nano\n", 
            spec.tv_sec, spec.tv_nsec );
    for ( int i = 0 ; i < TESTRUNS ; ++ i )
    {
        clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &spec );
    }
    double fb = Get_FloatTime();
    printf( "clock_gettime %d iterations : %.6f msec %.3f microsec / call\n",
        TESTRUNS, ( fb - fa ) * 1000.0, (( fb - fa ) * 1000000.0) / TESTRUNS );
}
// and so on for CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID.

结果:

CLOCK_PROCESS_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 3115.784947 msec 0.371 microsec / call
CLOCK_MONOTONIC resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2505.122119 msec 0.299 microsec / call
CLOCK_REALTIME resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2456.186031 msec 0.293 microsec / call
CLOCK_THREAD_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2956.633930 msec 0.352 microsec / call

这是在标准的 Ubuntu 内核上。该应用程序是 Windows 应用程序的端口(我们的 rdtsc 内联程序集在其中运行良好)。

附录:

x86-64 GCC 是否有一些与 __rdtsc() 的内在等价物,所以我至少可以避免内联汇编?

最佳答案

没有。您必须使用特定于平台的代码来执行此操作。在 x86 和 x86-64 上,您可以使用“rdtsc”来读取 Time Stamp Counter .

只需移植您正在使用的 rdtsc 程序集即可。

__inline__ uint64_t rdtsc(void) {
  uint32_t lo, hi;
  __asm__ __volatile__ (      // serialize
  "xorl %%eax,%%eax \n        cpuid"
  ::: "%rax", "%rbx", "%rcx", "%rdx");
  /* We cannot use "=A", since this would use %rax on x86_64 and return only the lower 32bits of the TSC */
  __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
  return (uint64_t)hi << 32 | lo;
}

关于linux - clock_gettime() 是否适合亚微秒计时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7935518/

相关文章:

mysql - 提高 MySQL LIKE 查询的速度?

linux - 五笔的工作?

Github 错误添加 https 来源,但它给了我错误 ---verbose

linux - 是否有一个与 fscanf 等效的 c 运行时函数,它包含相同的参数列表?

linux - gdb 回溯和 pthread_cond_wait()

java - 如何在Linux操作系统的NetBeans上连接MySql?

sql - 性能 createNamedNativeQuerie 与 createNativeQuery

linux - 一定数量的字节等于多少页?

mysql - 构建用户收藏夹表的正确方法是什么(性能)

android-studio - Android Studio 未在 Ubuntu 20.04 中启动,因为我从 Andrioid Studio 设置中编辑了 vmoptions