TSC Frequency For All: Better Profiling and Benchmarking
你是否曾尝试使用LLVM的X-Ray分析工具生成火焰图,却遇到类似这样的错误:
==65892==Unable to determine CPU frequency for TSC accounting.
==65892==Unable to determine CPU frequency.
或者更糟:当分析完应用程序的所有函数后,发现所有函数运行时间总和只有15分钟,而实际运行耗时20分钟——那消失的5分钟去哪了?
我们遇到了这些问题,因此开发了名为tsc_freq_khz
的Linux内核模块解决方案。在深入x86计时器原理之前,先看核心改进:该模块能消除虚拟化环境中X-Ray等工具的"无法确定CPU频率"错误,并在新一代Intel处理器上提供更精确的时间测量。
从时间戳到纳秒
x86架构至少有六种计时方式,其中时间戳计数器(TSC)因其低延迟和用户态直接访问的特性,成为性能分析工具的首选。但TSC以"滴答"为单位,需要乘以TSC频率才能转换为纳秒:
time_in_nanoseconds = (tsc_count_end - tsc_count_start) * tsc_frequency
现有方案的缺陷
传统方案存在两个关键问题:
- 在新Intel CPU上,最大时钟速度已不能准确代表TSC频率
- 虚拟化环境中
/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq
通常不可用
Google的启示
我们在X-Ray和Abseil代码中发现它们会检查/sys/devices/system/cpu/cpu0/tsc_freq_khz
文件,但该功能仅存在于Google定制内核中。于是我们开发了同名内核模块,通过sysfs导出内核启动时计算的tsc_khz
变量。
使用方式
- 编译并插入内核模块:
$ sudo insmod ./tsc_freq_khz.ko
$ dmesg | grep tsc_freq_khz
[14045.345025] tsc_freq_khz: starting driver
- 查询频率值:
$ cat /sys/devices/system/cpu/cpu0/tsc_freq_khz
2712020
警告:当前实现假设CPU0存在且未进行有效性检查,不建议用于生产环境
结语
这个小而美的解决方案填补了Linux内核的功能空白,为性能分析工具提供了关键的时间测量基础。随着技术演进,该功能可能会被纳入官方内核,而目前tsc_freq_khz
模块可作为临时解决方案。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
公众号二维码