发现以下内容时,我正在阅读.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” 是.NET运行时的一部分,它将intermediate language (IL) (i.e. .NET "bytecode")转换为计算机的汇编语言。只有这样,您的计算机才能执行代码。 JIT仅在实际需要时才按方法执行此转换方法:每当首次调用方法时,它都会首先编译为实际的汇编语言,即“即时”(JIT)。
C#编译器不会立即为您的计算机体系结构生成汇编语言。相反,它生成intermediate language,这是抽象堆栈机的某种汇编语言(已在ECMA 334 international standard中定义)。
例如,对参数的分配(在您的示例中为value
)将由C#编译器转换为一条称为的IL指令starg
(“存储到参数”)。
注释基本上说,如果该方法包含这样的分配(value = …
),则JIT当前将无法对其进行“内联”。 "Inlining a method" 意味着JIT不会生成方法的调用指令(即,将命令转移到不同的代码位置),而是将方法的整个主体插入到被调用的位置。通常这样做是为了优化执行速度,因为不需要分支/跳转,此外,我还假定也不必设置新的堆栈框架。
通过分配给局部变量(value_copy = …
),可以避免JIT的这种限制,因为对局部变量的赋值会生成另一条IL指令:stloc
(“存储到局部变量”)。
另请参阅:
关于c# - .NET局部变量优化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26369163/