如何解读perf统计中iTLB-loads与iTLB-load-misses的异常数值?
先看你给出的观测命令和输出结果:
观测命令:
perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses -p 22479输出结果:
Performance counter stats for process id '22479': 1,262,817 dTLB-loads 13,950 dTLB-load-misses # 1.10% of all dTLB cache hits 75 iTLB-loads 6,882 iTLB-load-misses # 9176.00% of all iTLB cache hits 3.999720948 seconds time elapsed
你觉得反常的点完全合理——正常情况下缺失次数不可能超过总加载次数,更别说百分比突破100%了。这背后的核心原因是Intel CPU上这两个perf事件的统计范围不匹配:
iTLB-loads:仅统计用户空间的指令页TLB加载请求,也就是你的进程执行自身代码时触发的ITLB查询。iTLB-load-misses:统计所有特权级别(用户态+内核态)的指令页TLB缺失事件,包括进程触发系统调用、中断时,内核代码执行产生的ITLB缺失。
具体发生了什么?
你的进程22479在运行过程中,肯定会频繁和内核交互:比如读写文件、发起网络请求(触发系统调用),或者被时钟中断打断(内核调度切换)。这些场景下CPU会切换到内核态执行内核代码,而内核的指令页同样需要从ITLB获取地址映射。如果这些内核指令的ITLB缓存没命中,这些缺失会被算进iTLB-load-misses,但对应的加载请求不会被计入iTLB-loads(因为这个事件只统计用户态操作)。
所以你看到的6882次缺失,几乎全是内核态操作带来的,而用户态的ITLB加载只有75次,自然就出现了缺失数远大于加载数的反常情况,那个9176%的百分比也完全没有参考价值——因为perf是直接用缺失数除以加载数计算的,但两者的统计基准根本不一致。
怎么得到准确的统计结果?
如果你想计算用户态真正的ITLB缺失率,可以用perf的事件修饰符来区分用户态和内核态:
perf stat -e iTLB-loads,iTLB-load-misses:u,iTLB-load-misses:k -p 22479
这里:
iTLB-load-misses:u:仅统计用户态的ITLB缺失iTLB-load-misses:k:仅统计内核态的ITLB缺失
此时用iTLB-load-misses:u除以iTLB-loads得到的就是正常的用户态ITLB缺失率,而iTLB-load-misses:u + iTLB-load-misses:k就等于你之前看到的6882次总缺失。
另外,如果你需要统计全特权级的ITLB加载请求,可以查看本地支持的对应事件(比如itlb_fetches.any),用perf list | grep iTLB就能看到所有相关事件。
内容的提问来源于stack exchange,提问作者barfatchen

