performance - 为什么这个间接调用(调用 rax)平均需要超过 100 个周期?
问题描述
编辑:这个问题是一个错误。我误读了在子例程中花费的时间,并认为该例程中的语句占用了总时间的 15%,而不是实际的 3%。
由于答案的高质量,我将问题留在这里。令我惊讶的是,即使目的地始终是相同的地址,计算的分支似乎也丢失了,我将使用那里的建议进行调查。
原来的:
这是我的 C 代码中的关键点,带有来自分析器的注释。间接调用占用了几百行循环总时间的三分之一。根据总运行时间,此调用语句必须至少占用 100 个时钟周期。
以下是最后 3 个 C 语句的生成代码:
00007FFE066FB5EA mov r12,qword ptr [r8+8]
00007FFE066FB5EE and r12d,30000h
00007FFE066FB5F5 dec r12
00007FFE066FB5F8 and r12,qword ptr [r8+20h]
00007FFE066FB5FC sar r12,3Fh
00007FFE066FB600 and r12,qword ptr [r8+10h]
00007FFE066FB604 lea rbx,[validitymask+60h (07FFE06B058E0h)]
00007FFE066FB60B cmove r12,rbx
A *tpopa=AZAPLOC(arg1); tpopa=(A*)((I)tpopa&REPSGN(AC(arg1)&((AFLAG(arg1)&(AFVIRTUAL|AFUNINCORPABLE))-1))); tpopa=tpopa?tpopa:ZAPLOC0; tpopw=(pline&2)?tpopw:tpopa; // monad: w fs dyad: a w if monad, change to w w
00007FFE066FB60F mov rsi,qword ptr [rdx+8]
00007FFE066FB613 and esi,30000h
00007FFE066FB619 dec rsi
00007FFE066FB61C and rsi,qword ptr [rdx+20h]
00007FFE066FB620 sar rsi,3Fh
00007FFE066FB624 and rsi,qword ptr [rdx+10h]
00007FFE066FB628 cmove rsi,rbx
00007FFE066FB62C test r15b,2
00007FFE066FB630 cmove r12,rsi
y=(*actionfn)((J)((I)jt+(REPSGN(SGNIF(pt0ecam,VJTFLGOK1X+(pline>>1)))&(pline|1))),arg1,arg2,fs); // set bit 0, and bit 1 if dyadic, if inplacing allowed by the verb
00007FFE066FB634 mov bl,28h
00007FFE066FB636 sub bl,cl
00007FFE066FB638 shlx rcx,rdi,rbx
00007FFE066FB63D sar rcx,3Fh
00007FFE066FB641 or r15d,1
00007FFE066FB645 and ecx,r15d
00007FFE066FB648 add rcx,r10
00007FFE066FB64B vzeroupper
00007FFE066FB64E call rax
正如你所看到的,除了调用 rax之外,有问题的语句并没有什么奇异之处。我希望该调用会创建可能 15 个时钟的管道中断,但与我所看到的完全不同。事实上,这段代码是循环执行的,而且大多数时候函数地址是相同的,所以我希望大多数间接调用都能正确预测。但这肯定不是我所看到的。
加载分支地址的指令(在所示的第一个 C 语句中)在使用分支地址之前很久就执行了;即,地址已确定。
为什么这个语句/指令这么慢?
第二个问题:出于分析目的,该语句何时结束?如果调用 rax需要管道中断,那么在中断期间发生的所有中断是否都计入调用 rax?这是有道理的,但其他指令仍在执行,对吧?
解决方案
推荐阅读
- unity3d - 团结,对角线子弹
- rest - 有没有办法通过 REST API 导入 Google Play 控制台安装报告?
- mysql - 将空值设置为非空列(`disc_base_pct` decimal(7,4) NOT NULL DEFAULT '-1.0000' ),但未获得默认值
- macos - 如何让 Apache 访问 MacOS Catalina 上的外部驱动器
- python - Whereis CUDA/Cuda/cuda - Ubuntu 20.4 - cuda 安装问题
- php - PHP foreach 循环数组错误为“未定义变量”但值存在
- zoho - 接收 Xero 和 Zoho Flow 的意向
- javascript - 存在带有 React 编译错误标识符的 Firebase
- go - 如何在 go 包之外运行测试 go 文件?
- ruby-on-rails - 呈现 json 响应时更改创建的 JSON 对象键