gpt4 book ai didi

C# 到 CIL 拳击 vs. ToString 成本

转载 作者:行者123 更新时间:2023-12-03 18:52:52 25 4
gpt4 key购买 nike

我正在通过 C#(第 4 版)阅读 CLR 一书,不是作为 C# 的新手,而是作为了解该语言的人试图提高我对 CLR 底层功能的掌握。

无论如何,在这本书中给出了一个例子 (pg127-131),当讨论值类型的装箱/拆箱时,它以调用 Console.WriteLine 结束,值类型被连接到作为参数传递的字符串。

这本书解释了装箱和拆箱/复制操作会导致开销,我已经知道这一点,但随后说明可以通过在传入的值类型上运行 .ToString() 来优化示例。

我创建了一个示例程序并编译它,然后使用 ILDASM 来检查它生成的 IL。带有 ToString 的版本本质上是相同的,但用对 ToString 的“调用”替换了“box”指令(没有震惊)。

我在 100000 次运行的循环中对代码进行了基准测试,没有任何区别(它波动哪个更快)。我意识到在进行基准测试(缓存等)时其他因素会起作用,但是通过本书解释它的方式,我曾期望即使在幼稚的基准测试中避免“box”指令时也会看到显着差异。

只是调用函数并没有好得多吗? ToString 中是否有一个装箱操作使好处无效并且书是错误的?有人可以对此有所了解吗?

作为引用,这里有两个 ILDASM 读数:

.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// Code size 24 (0x18)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.4
IL_0001: stloc.0
IL_0002: ldloc.0
IL_0003: box [mscorlib]System.Int32
IL_0008: ldstr "."
IL_000d: call string [mscorlib]System.String::Concat(object,
object)
IL_0012: call void [mscorlib]System.Console::WriteLine(string)
IL_0017: ret
} // end of method Program::Main
.method private hidebysig static void  Main(string[] args) cil managed
{
.entrypoint
// Code size 25 (0x19)
.maxstack 2
.locals init (int32 V_0)
IL_0000: ldc.i4.4
IL_0001: stloc.0
IL_0002: ldloca.s V_0
IL_0004: call instance string [mscorlib]System.Int32::ToString()
IL_0009: ldstr "."
IL_000e: call string [mscorlib]System.String::Concat(string,
string)
IL_0013: call void [mscorlib]System.Console::WriteLine(string)
IL_0018: ret
} // end of method Program::Main

最佳答案

CLR 可能会将调用内联到 string.Concat(object,object)这会产生与您的“优化”版本相同的代码。请注意,C# 编译器会将很多此类优化留给 CLR,因为它有更好的工具可以执行这些优化。

除了几个空检查(将被优化掉)之外,它只是调用 string.Concat(left.ToString(),right.ToString())这将简化为 string.Concat(left,right.ToString())因为 CLR 会看到 ToString()刚刚返回 this .

因此,两种情况下的执行代码可能相同。

关于C# 到 CIL 拳击 vs. ToString 成本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28995660/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com