++;我和我++;在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)
}