当前位置:  开发笔记 > 编程语言 > 正文

C#中的++ i和i ++之间是否存在任何性能差异?

如何解决《C#中的++i和i++之间是否存在任何性能差异?》经验,为你挑选了4个好方法。

使用类似的东西是否有任何性能差异

for(int i = 0; i < 10; i++) { ... }

for(int i = 0; i < 10; ++i) { ... }

或者编译器是否能够以这样的方式进行优化,使它们在功能相同的情况下同样快速?

编辑:这是因为我与同事讨论过这个问题,并不是因为我觉得它在任何实际意义上都是有用的优化.它主要是学术性的.



1> Jim Mischel..:

在这种情况下,生成的++ i和i ++中间代码没有区别.鉴于此计划:

class Program
{
    const int counter = 1024 * 1024;
    static void Main(string[] args)
    {
        for (int i = 0; i < counter; ++i)
        {
            Console.WriteLine(i);
        }

        for (int i = 0; i < counter; i++)
        {
            Console.WriteLine(i);
        }
    }
}

两个循环生成的IL代码相同:

  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  // Start of first loop
  IL_0002:  ldc.i4.0
  IL_0003:  stloc.0
  IL_0004:  br.s       IL_0010
  IL_0006:  ldloc.0
  IL_0007:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_000c:  ldloc.0
  IL_000d:  ldc.i4.1
  IL_000e:  add
  IL_000f:  stloc.0
  IL_0010:  ldloc.0
  IL_0011:  ldc.i4     0x100000
  IL_0016:  blt.s      IL_0006
  // Start of second loop
  IL_0018:  ldc.i4.0
  IL_0019:  stloc.0
  IL_001a:  br.s       IL_0026
  IL_001c:  ldloc.0
  IL_001d:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_0022:  ldloc.0
  IL_0023:  ldc.i4.1
  IL_0024:  add
  IL_0025:  stloc.0
  IL_0026:  ldloc.0
  IL_0027:  ldc.i4     0x100000
  IL_002c:  blt.s      IL_001c
  IL_002e:  ret

也就是说,JIT编译器可以(尽管不太可能)在某些上下文中进行一些优化,这些上下文有利于一个版本而不是另一个版本.但是,如果存在这样的优化,则可能仅影响循环的最终(或可能是第一次)迭代.

简而言之,在您描述的循环结构中,控制变量的简单预增量或后增量的运行时间没有区别.


在C ++中,虽然有所不同,但预递增速度更快。我认为C#没有任何区别。
@Ysha不,C ++没有区别。有关详细信息,请参见/sf/ask/17360801/。现在,如果它不是简单类型的增量内容,则可能有所不同。但是,在此问答中,没有任何内容。

2> Joe..:

啊......再打开一次.好.这是交易.

ILDASM是一个开始,但不是目的.关键是:JIT将为汇编代码生成什么?

这是你想要做的.

拿几个你想看的样品.显然,如果你愿意,你可以按时间计时 - 但我认为你想了解更多.

这是不明显的.C#编译器会生成一些在很多情况下都不是最优的MSIL序列.它调整的JIT用于处理来自其他语言的这些和怪癖.问题是:只有有人注意到的'怪癖'已被调整.

你真的想制作一个样本,让你的实现尝试,返回到main(或任何地方),Sleep(),或者你可以附加调试器的东西,然后再次运行例程.

您不希望在调试器下启动代码,或者JIT将生成非优化代码 - 听起来您想知道它在真实环境中的行为方式.JIT执行此操作以最大化调试信息并最小化当前源位置"跳转".永远不要在调试器下启动性能评估.

好.因此,一旦代码运行一次(即:JIT已为其生成代码),则在睡眠期间(或其他)附加调试器.然后查看为这两个例程生成的x86/x64.

我的直觉告诉我,如果你正在使用++ i/i ++,就像你所描述的那样 - 即:在一个独立的表达式中,rvalue结果不会被重复使用 - 就没有区别了.但是去看看所有整洁的东西不是很有趣!:)



3> Jay Bazuzi..:

如果你问这个问题,那你就试图解决错误的问题.

要问的第一个问题是"如何通过提高运行速度来提高客户对软件的满意度?" 答案几乎从不"使用++ i代替i ++",反之亦然.

来自Coding Horror的帖子" 硬件很便宜,程序员很贵 ":

优化
规则:规则1:不要这样做.
规则2(仅限专家):不要这样做.
- MA杰克逊

我将规则2理解为"首先编写干净,清晰的代码以满足客户的需求,然后在速度太慢的情况下加速".++ivs i++将成为解决方案的可能性极低.


我从未想过"哪一个更快"的问题.我总是使用`++ i`.为什么?因为我从左到右阅读*并且`++ i`被读作"增加`i`的值"而不是"带'i`并增加其值".由于`++`在左侧,我可以立即看到发生了什么,我不需要向右移动我的眼球:)如果你有一个长变量名,那么`++ something`就更具可读性了.
-1:在忽略真实问题时回答OP从未问过的问题.也叫OP一个巨魔.

4> Rasmus Faber..:

正如Jim Mischel 所示,编译器将为两种写入for循环的方式生成相同的MSIL.

但就是这样:没有理由推测JIT或进行速度测量.如果两行代码生成相同的MSIL,它们不仅执行相同,而且实际上是相同的.

没有可能的JIT能够区分循环,因此生成的机器代码也必须是相同的.

推荐阅读
个性2402852463
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有