为什么代码大小对JIT编译很重要?

时间:2016-07-20 01:55:36

标签: c# performance assembly jit

假设您正在使用JIT编译的语言进行开发。在生成的程序集的代码大小方面,是否存在使功能非常大的性能缺点?

我问,因为我前几天在C#中查看Buffer.MemoryCopy的源代码,这显然是一种对性能非常敏感的方法。看起来他们使用大switch语句来专门化所有字节数< = 16的函数,从而导致生成some pretty gigantic汇编。

这种方法在性能方面是否有任何缺点?例如,我注意到memmove的{​​{3}}和glibc实现不执行此操作,尽管事实上C是AOT编译的,这意味着它不会受到影响FreeBSD的成本(这是一个缺点) - 对于C#,JIT等到第一次调用编译方法,因此对于很长的方法,第一次调用将花费更长的时间。

对于JIT编辑的语言,有一个巨大的switch语句和增加的代码大小(除了我刚才提到的预编译成本之外)有什么上升/下降?谢谢。 (我对装配有点新意,所以请放轻松我:))

1 个答案:

答案 0 :(得分:4)

假设是x86。

获取 1 并解码 2 指令不是免费的。

与数据缓存类似,CPU具有代码缓存;但它通常较小,从8 KiB到32 KiB不等 较短的代码更适合I-cache,需要较少的内存提取。

然而,获取只是故事的一半 由于其(非常)可变长度指令,x86在解码方面存在历史问题。 已经存在并且存在各种模式以及解决方法以实现快速解码的限制。

自Core2架构以来,CPU有其他指令缓存,位于解码器 3 之后。
这些缓存保存已经解码的指令,绕过前一阶段的限制和延迟。

只是为了有一个心理想法我勾勒出Haswell解码单元 4

Haswell decoding

每个箭头都是数据路径中的一个步骤,通常需要一个时钟 阴暗区域是可以找到指令的地方。

缓存越接近Out of Order core 5 ,意味着位于底部,所述缓存中的指令可以越快到达核心。
然而,越接近缓存越小,因此减小代码大小可以提高性能,特别是对于关键循环 6

我根据对Agner Fog的分析得出了这些结论。

1 从记忆中读取的行为 2 将指令转换为微操作的操作 3 Core2的预解码器,但仍然 4 彼得,欢迎你指出错误:) 5 有效执行指令的CPU部分 6 循环意味着经常执行。