gpt4 book ai didi

c# - 在循环条件之外为循环条件声明变量是否更快?

转载 作者:行者123 更新时间:2023-11-30 14:46:21 25 4
gpt4 key购买 nike

在下面的场景中,示例 1 是否比示例 2 快?为什么?

示例 1

int c = myArray.Count;
for (int i = 0; i < c; i++)
{
Console.WriteLine(myArray[i]);
}

示例 2

for (int i = 0; i < myArray.Count; i++)
{
Console.WriteLine(myArray[i]);
}

最佳答案

让我们获取 IL 代码,看看 Release 配置中发生了什么。

    /* 0x0000027B 6F0D00000A   */ IL_001F: callvirt  instance int32 class [System.Collections]System.Collections.Generic.List`1::get_Count()    /* 0x00000280 0B           */ IL_0024: stloc.1    /* 0x00000281 16           */ IL_0025: ldc.i4.0    /* 0x00000282 0C           */ IL_0026: stloc.2    /* 0x00000283 2B10         */ IL_0027: br.s      IL_0039    // loop start (head: IL_0039)        /* 0x00000285 06           */ IL_0029: ldloc.0        /* 0x00000286 08           */ IL_002A: ldloc.2        /* 0x00000287 6F0E00000A   */ IL_002B: callvirt  instance !0 class [System.Collections]System.Collections.Generic.List`1::get_Item(int32)        /* 0x0000028C 280F00000A   */ IL_0030: call      void [System.Console]System.Console::WriteLine(char)        /* 0x00000291 08           */ IL_0035: ldloc.2        /* 0x00000292 17           */ IL_0036: ldc.i4.1        /* 0x00000293 58           */ IL_0037: add        /* 0x00000294 0C           */ IL_0038: stloc.2        /* 0x00000295 08           */ IL_0039: ldloc.2        /* 0x00000296 07           */ IL_003A: ldloc.1        /* 0x00000297 32EC         */ IL_003B: blt.s     IL_0029    // end loop    /* 0x00000299 16           */ IL_003D: ldc.i4.0    /* 0x0000029A 0D           */ IL_003E: stloc.3    /* 0x0000029B 2B10         */ IL_003F: br.s      IL_0051    // loop start (head: IL_0051)        /* 0x0000029D 06           */ IL_0041: ldloc.0        /* 0x0000029E 09           */ IL_0042: ldloc.3        /* 0x0000029F 6F0E00000A   */ IL_0043: callvirt  instance !0 class [System.Collections]System.Collections.Generic.List`1::get_Item(int32)        /* 0x000002A4 280F00000A   */ IL_0048: call      void [System.Console]System.Console::WriteLine(char)        /* 0x000002A9 09           */ IL_004D: ldloc.3        /* 0x000002AA 17           */ IL_004E: ldc.i4.1        /* 0x000002AB 58           */ IL_004F: add        /* 0x000002AC 0D           */ IL_0050: stloc.3        /* 0x000002AD 09           */ IL_0051: ldloc.3        /* 0x000002AE 06           */ IL_0052: ldloc.0        /* 0x000002AF 6F0D00000A   */ IL_0053: callvirt  instance int32 class [System.Collections]System.Collections.Generic.List`1::get_Count()        /* 0x000002B4 32E7         */ IL_0058: blt.s     IL_0041    // end loop

There is one obvious difference between both, in the latter method you are calling virtual instance method on each iteration and on the other only once before the loop.

IL instructions are relatively the same number so unless you think that this callvirt(why callvirt for instance method? because it has nice null check that comes with it and compiler uses it for non-virtual methods as well) instruction will drag you down I am suggesting you do choose what is best practice that potentially small performance tweak will not worth it I guarantee it, not to mention that JIT can also do some optimizations - I will be not surprised.


UPDATE: Benchmarks with BenchmarkDotNet with attaached debugger.

       Method |     Mean |     Error |    StdDev |
------------- |---------:|----------:|----------:|
OutsideCount | 25.04 ns | 0.3334 ns | 0.2955 ns |
InsideCount | 26.13 ns | 0.5295 ns | 0.6502 ns |
Foreach | 40.59 ns | 0.3848 ns | 0.3599 ns |

同样,这是非常特定于硬件的,但为了论证而展示它。

关于c# - 在循环条件之外为循环条件声明变量是否更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49506620/

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