++;我和我++;在C#中?

++;我和我++;在C#中?,c#,operators,performance,C#,Operators,Performance,使用类似于 for(int i = 0; i < 10; i++) { ... } for(inti=0;i

使用类似于

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

(inti=0;i<10;++i){…} 或者,编译器是否能够以这样一种方式进行优化,即在功能上相同的情况下,它们的速度相同

编辑: 问这个问题是因为我和一位同事讨论过这个问题,而不是因为我认为这是一个实用的优化。这主要是学术性的

根据,i++使用的CPU指令多于++i。但这是否会导致性能差异,我不知道


由于任何一个循环都可以很容易地重写为使用后增量或预增量,我想编译器将始终使用更高效的版本。

啊。。。再次打开。好啊事情是这样的

ILDASM是一个开始,但不是结束。关键是:JIT将为汇编代码生成什么

这是你想要做的

拿几个你想看的东西的样本。很明显,如果你想的话,你可以用挂钟给他们计时——但我想你想知道的不止这些

这是不明显的。C#编译器生成的一些MSIL序列在很多情况下都是非最优的。JIT it调整以处理这些问题和来自其他语言的怪癖。问题是:只有人们注意到的“怪癖”被调整了

您确实希望制作一个示例,让您的实现可以尝试,返回main(或任何位置)、Sleep()或其他可以附加调试器的地方,然后再次运行例程

您不想在调试器下启动代码,否则JIT将生成未优化的代码——听起来您想知道它在真实环境中的行为。JIT这样做是为了最大化调试信息,并将当前源位置从“跳转”最小化。切勿在调试器下启动性能评估

嗯。因此,一旦代码运行了一次(即:JIT为其生成了代码),那么就在睡眠期间附加调试器(或其他)。然后看看为这两个例程生成的x86/x64


我的直觉告诉我,如果你像你所描述的那样使用++i/i++,也就是说,在一个独立的表达式中,不重复使用右值结果,那么就不会有什么区别。但是去发现并看到所有整洁的东西不是很有趣吗!:)

有一段具体的代码和CLR版本吗?如果是这样的话,对其进行基准测试。如果没有,那就忘了它。微观优化,以及所有这些。。。此外,您甚至不能确定不同的CLR版本是否会产生相同的结果。

static void Main(string[]args){
  static void Main(string[] args) {
     var sw = new Stopwatch(); sw.Start();
     for (int i = 0; i < 2000000000; ++i) { }
     //int i = 0;
     //while (i < 2000000000){++i;}
     Console.WriteLine(sw.ElapsedMilliseconds);
var sw=新秒表();sw.Start(); 对于(int i=0;i<2000000000;++i){ //int i=0; //而(i<20000000000){++i;} 控制台写入线(软件延迟毫秒);
3次运行的平均值:
对于带有i++:1307的 对于使用++i:1314

使用i++:1261时 当使用++i时:1276


这是一个2,53 Ghz的Celeron D。每次迭代大约需要1.6个CPU周期。这要么意味着CPU每个周期执行超过1条指令,要么是JIT编译器展开了循环。i++和++i之间的差异是每次迭代只有0.01个CPU周期,可能是由后台的OS服务造成的。

没有问题在本例中,++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);
        }
    }
}
也就是说,JIT编译器有可能(尽管不太可能)在某些上下文中进行某些优化,使一个版本优于另一个版本。但是,如果存在这样的优化,它可能只会影响循环的最终(或者可能是第一次)迭代


简而言之,在您所描述的循环构造中,控制变量的简单增量前或增量后的运行时将没有区别。

如果您问这个问题,您试图解决错误的问题

要问的第一个问题是“如何通过加快软件的运行速度来提高客户对软件的满意度?”答案几乎永远不会是“使用++I而不是I++”,反之亦然

从《恐怖的帖子》中:

优化规则:
规则1:不要这样做。
规则2(仅限专家):暂时不要这样做。
--

我认为规则2的意思是“首先编写满足客户需求的干净、清晰的代码,然后在速度太慢的地方加速”。很可能
++I
I++
是解决方案。

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

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


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

除了其他答案之外,如果您的
i
在C++中不是
int
,如果它是具有运算符
+()
++(int)
过载,则可能会产生影响,可能会产生副作用。在这种情况下,
++i
的性能应该更好(取决于实现)。

两者之间没有区别, 原因是循环内比较是在递增/递减语句之后的一个单独语句。 榜样

for(int i=0; i<3; i++){
    System.out.println(i)
}

for(int i=0;它不应该被关闭。但是无论如何,如果你编译它并使用ildasm.exe查看MSIL,你会看到这两个示例产生相同的MSIL。投票重新打开。给John Sheehan,tvanfosson,ctacke,Marc Gravell。。如果你投票关闭。。编辑并提供问题中的副本!我明白了
  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
for(int i=0; i<3; i++){
    System.out.println(i)
}