x86_64 - 自修改代码性能

x86_64 - Self-modifying code performance

我正在阅读英特尔架构文档,第 3 卷,第 8.1.3 节

Self-modifying code will execute at a lower level of performance than non-self-modifying or normal code. The degree of the performance deterioration will depend upon the frequency of modification and specific characteristics of the code.

所以,如果我遵守规则:

(* OPTION 1 *) Store modified code (as data) into code segment; Jump to new code or an intermediate location; Execute new code;

(* OPTION 2 ) Store modified code (as data) into code segment; Execute a serializing instruction; ( For example, CPUID instruction *) Execute new code;

AND 修改代码每周一次,我应该只在下次修改此代码并即将执行时支付罚款。但在那之后,性能应该与未​​修改的代码相同(+跳转到该代码的成本)。

我的理解正确吗?

"The next time"大概不是这样;缓存算法考虑了第一个之外的访问(不这样做会很天真)。然而,在前几次访问后不久,惩罚应该消失了。 ("Few" 可能是两个或数千个,但对于计算机来说,即使是一百万也不算什么。)

即使是当前正在执行的代码也在某个时候写入了内存(甚至可能是最近由于分页),所以它最初会经历类似的惩罚,但很快就会消失,所以你不必担心。

根本还没有缓存的代码与修改已经推测在飞行中的指令的代码(获取,可能解码,甚至可能坐在调度程序中并在输出中重新排序缓冲区)之间存在差异订单核心)。写入已被 CPU 视为指令的内存会导致它退回到非常缓慢的操作。这就是自修改代码的通常含义。即使 JIT 编译不是太难,也可以避免这种减速。在全部写入之前不要跳转到缓冲区。

每周修改一次意味着如果你做错了,你可能每周会有一次一微秒的惩罚。确实,经常使用的数据不太可能被从缓存中逐出(这就是为什么多次读取某些东西更有可能成为它 "stick"),但是自修改代码管道刷新应该只应用第一次,如果你遇到它的话。在那之后,正在执行的缓存行很可能。如果第二个 运行 在没有太多干预代码的情况下发生,则在 L1 I-cache(和 uop 缓存)中仍然很热。它在 L1 D 缓存中尚未处于修改状态。

忘记了http://agner.org/optimize/是否讲了自修改代码和JIT。即使没有,如果您正在使用 ASM 编写任何内容,您也应该阅读 Agner 的指南。不过,主要 "optimizing asm" 中的一些内容已经过时,与 Sandybridge 和后来的英特尔 CPU 无关。由于 uop 缓存,对齐/解码问题不再是问题,对齐问题对于 SnB 系列微架构可能有所不同。