例如:
代码1:
void Main()
{
Console.WriteLine("Some texts");
}
代码2:
void Main()
{
Foo();
}
void Foo()
{
Console.WriteLine("Some texts");
}
代码2的运行速度是否慢于代码1?我在构建版本时,JIT将内联代码2,然后代码2将以代码1的速度运行。但是当我用LinqPad测试它时,我得到了IL结果:
代码1:
IL_0000: ldstr "Some texts"
IL_0005: call System.Console.WriteLine
代码2:
IL_0000: ldarg.0
IL_0001: call UserQuery.Foo
Foo:
IL_0000: ldstr "Some texts"
IL_0005: call System.Console.WriteLine
IL_000A: ret
正如我们所看到的,代码2中的IL结果有一些额外的步骤来调用Foo(),这是否证明代码2的运行速度比代码1慢?
答案 0 :(得分:10)
首先,您正在查看IL,而不是JITted汇编代码。你所展示的并不能证明什么。您需要查看JITted输出以查看JITter是否内联了代码。请注意,JITter从平台到平台(例如x86与x64)以及Framework的版本与Framework的版本不同。
其次,当然,由于书面版本2的运行速度比版本1慢。当我说“as written”时,我的意思是假设JITter没有在第二版中内联调用。额外的调用添加了一些机器指令,当然需要几个额外的周期来执行(再次,不要忘记我说“写的!”)。然而,性能上的差异非常极大,不太可能有意义。您必须在最紧密的循环中进行数万亿次和数万亿次迭代才能看到有意义的性能差异。
答案 1 :(得分:2)
是的方法调用会使代码执行变慢一点,如果它们没有被c#-compiler或jit-compiler内联。但是,除非您的代码在循环中运行并且执行了一百万次左右,否则您应该专注于生成干净,易懂和可维护的代码。当我开始编写单个语句的执行时间时,以毫秒或微秒为单位进行测量。今天它们以纳秒为单位。时间通常主要浪费在I / O操作上。糟糕的算法也可能被指责一些。如果您的设计结构清晰,那么将一个性能较差的代码部分替换为一个更好的代码部分将比从一开始就进行时间优化的代码更容易,因此可能结构很糟糕。
我最近经历过这一点。我必须在一个c#程序中在Visio中生成一个复杂的图形。原来,Visio自动化非常缓慢。创建图形需要几分钟。幸运的是,我已将所有图形内容放在一个组件中,该组件通过产品中性界面显示图形命令。即:界面不包含任何Visio特定的东西。用一个新的SVG组件替换我的Visio组件非常容易,它在不到一秒的时间内完成了相同的任务。此外,绝对不能在我的算法或程序的任何其他部分进行任何更改。
原因是,我的图形包装器组件添加了更多的方法调用。此外,它可以通过界面访问,这会使整个事情变得更加缓慢。但是,最后,正是这个接口和这些额外的方法调用,使我能够实现更快的解决方案。记住:分钟与不到一秒!
答案 2 :(得分:2)
在这种情况下,实现是我最后一次阅读这些内容,是的,它将被内联。
一般来说,答案可能是 - 关于内联规则的内容是哪些文档是信息材料,主要是在博客中,而不是规范性文档。不仅版本之间的细节也会发生变化,它们几乎肯定会发生。
在实践中:
如果您怀疑性能热点可以从手动内联中受益,那么请尝试并再次进行配置。或者至少查看该特定部分的jitted代码。
理论上:
尽管如此,我还是想知道小方法是内联的,都是一样的。
答案 3 :(得分:1)
它如此微不足道(读:可能有),你不应该担心它。
答案 4 :(得分:1)
C#编译器不进行内联,这就是您在IL代码中看到的内容。内联是JIT优化器的工作,它在运行时执行(如果它决定内联函数使程序更有效)。
答案 5 :(得分:0)
编译器创建自己对代码(汇编代码)的解释,因此代码示例将在CPU中以相同的方式处理。 (在发布模式下)