我正在尝试理解如何衡量性能,并决定编写一个非常简单的程序:
section .text
global _start
_start:
mov rax, 60
syscall我用perf stat ./bin运行了这个程序,我惊讶的是stalled-cycles-frontend太高了。
0.038132 task-clock (msec) # 0.148 CPUs utilized
0 context-switches # 0.000 K/sec
0 cpu-migrations # 0.000 K/sec
2 page-faults # 0.052 M/sec
107,386 cycles # 2.816 GHz
81,229 stalled-cycles-frontend # 75.64% frontend cycles idle
47,654 instructions # 0.44 insn per cycle
# 1.70 stalled cycles per insn
8,601 branches # 225.559 M/sec
929 branch-misses # 10.80% of all branches
0.000256994 seconds time elapsed根据我对stalled-cycles-frontend的理解,它意味着CPU前端必须等待某个操作(例如总线事务)的结果才能完成。
那么,是什么原因导致CPU前端在最简单的情况下等待了大部分时间呢?
和2个页面错误?为什么?我没有读到内存页。
发布于 2018-02-15 22:39:38
页面错误包括代码页。
perf stat包括启动开销。
IDK关于perf如何开始计数的细节,但大概它必须在内核模式下对性能计数器进行编程,所以它们会在CPU切换回用户模式时进行计数(停滞了许多周期,特别是在具有熔断防御功能的内核上,这会使TLB失效)。
我猜记录的大多数 47,654 指令都是内核代码。可能包括页面错误处理程序!
我猜您的进程永远不会进入用户->内核->用户,整个进程是内核->用户->内核(启动,syscall调用sys_exit,然后再也不会返回到用户空间),所以TLB无论如何都不会是热的,除非在sys_exit系统调用之后在内核中运行。无论如何,TLB未命中不是页面错误,但这可以解释许多停滞的周期。
用户->内核转换本身解释了大约150个停滞的周期,BTW。syscall比缓存未命中更快(除了它不是流水线的,实际上会刷新整个流水线;即特权级别不会被重命名)。
https://stackoverflow.com/questions/48809347
复制相似问题