St.*_*rio 11 linux performance assembly x86-64 perf
我试图了解如何衡量性能并决定编写非常简单的程序:
section .text
global _start
_start:
mov rax, 60
syscall
Run Code Online (Sandbox Code Playgroud)
我用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
Run Code Online (Sandbox Code Playgroud)
据我所知,stalled-cycles-frontend这意味着CPU前端必须等待某些操作(例如总线事务)的结果才能完成.
那么是什么导致CPU前端在最简单的情况下大部分时间都在等待?
和2页错误?为什么?我没有读内存页面.
页面错误包括代码页。
perf stat包括启动开销。
我不知道如何开始计数的细节perf,但大概它必须在内核模式下对性能计数器进行编程,因此它们在 CPU 切换回用户模式时进行计数(停滞许多周期,特别是在具有 Meltdown 防御的内核上,这会使TLB)。
我猜大部分47,654记录的指令都是内核代码。 也许包括页面错误处理程序!
我猜你的进程永远不会进入用户->内核->用户,整个过程是内核->用户->内核(启动,syscall调用sys_exit,然后永远不会返回到用户空间),所以永远不会出现TLB会具有的情况无论如何都很热,除了系统调用后在内核中运行时sys_exit。无论如何,TLB 未命中不是页面错误,但这可以解释许多停滞的周期。
顺便说一句,用户->内核转换本身解释了大约 150 个停滞周期。 syscall比缓存未命中更快(除了它不是流水线的,并且实际上刷新整个流水线;即特权级别没有重命名。)
用于perf stat --all-user仅在用户空间中计数。
或者对四个计数器进行编程,其中两个仅在用户模式下对和事件perf stat -e task-clock,cycles:u,instructions:u,cycles:k,instructions:k进行计数,两个仅在内核模式下对事件进行计数。(PMU 中有对此的硬件支持,因此用户空间的计数非常准确,只需要一两条指令。)instructionscycles
也可以看看
| 归档时间: |
|
| 查看次数: |
155 次 |
| 最近记录: |