.NET局部变量优化
本文关键字:优化 局部变量 NET | 更新日期: 2023-09-27 18:26:34
我在阅读.NET源代码时发现了以下内容:
// Constructs a Decimal from an integer value.
//
public Decimal(int value) {
// JIT today can't inline methods that contains "starg" opcode.
// For more details, see DevDiv Bugs 81184: x86 JIT CQ:
// Removing the inline striction of "starg".
int value_copy = value;
if (value_copy >= 0) {
flags = 0;
}
else {
flags = SignMask;
value_copy = -value_copy;
}
lo = value_copy;
mid = 0;
hi = 0;
}
正如您所看到的,Decimal结构的构造函数将方法参数复制到局部变量,而不是直接使用它。我想知道这个评论是什么意思,以及它与性能的关系;优化?
我的猜测是,一旦您想修改现有的参数,方法就不能再内联了?
http://referencesource.microsoft.com/#mscorlib/system/decimal.cs#f9a4da9d6e110054#references
我的猜测是,一旦
想要修改现有参数,方法就不能再内联了
简短回答:您的猜测是正确的(如果源代码注释今天仍然正确)。
// JIT today can't inline methods that contains "starg" opcode.
"JIT"是.NET运行时的一部分,用于将中间语言(IL)(即.NET"字节码")转换为计算机的汇编语言。只有这样,你的计算机才能执行代码。JIT逐方法执行此转换,并且仅在实际需要时执行:无论何时首次调用方法,都会首先将其编译为实际的汇编语言"即时"(JIT)。
C#编译器不会立即为计算机的体系结构生成汇编语言;相反,它生成中间语言,这是抽象堆栈机器的某种汇编语言(在ECMA334国际标准中定义)。
例如,对参数(在您的示例中为:value
)的赋值将由C#编译器转换为名为starg
("存储到参数")的IL指令。
注释基本上说,如果方法包含这样的赋值(value = …
),那么JIT当前将无法"内联"它。"内联方法"意味着JIT将在调用方法的位置插入方法的整个主体,而不是生成对方法的调用指令(即将命令分支到不同的代码位置)。这样做通常是为了优化执行速度,因为不需要分支/跳跃,此外,我认为也不必设置新的堆栈帧。
通过改为分配给局部变量(value_copy = …
),可以规避JIT的这一限制,因为分配给本地变量会导致生成不同的IL指令:stloc
("存储到局部变量")。
另请参阅:
- Andrey Akinshin:"关于JIT-x86内联和starg的故事"(博客文章)