.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

.NET局部变量优化

我的猜测是,一旦想要修改现有参数,方法就不能再内联了

简短回答:您的猜测是正确的(如果源代码注释今天仍然正确)。

//  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的故事"(博客文章)