我有一个数组,我想在同一个方法中多次使用单个值。
int[] array = new array[] {1, 2, 3};
现在我问你如果我使用数组和索引来获取值是否是一个大的性能问题......
int x = array[1] * 2;
int y = array[1] * 3;
int z = array[1] * 4;
还是创建一个局部变量更好?
int value = array[1];
int x = value * 2;
int y = value * 3;
int z = value * 4;
我知道使用局部变量更容易阅读,但如果它会产生任何性能差异,我就会感兴趣。 ;-)
虽然我同意这样的微优化是邪恶的并且是不必要的,而且可读性可能更重要,但是为两种方法制作一个虚拟基准还是很有趣的:
private static int TestWithIndex(int[] array)
{
int x = array[1] * 2;
int y = array[1] * 3;
int z = array[1] * 4;
return x + y + z;
}
private static int TestWithTemp(int[] array)
{
int value = array[1];
int x = value * 2;
int y = value * 3;
int z = value * 4;
return x + y + z;
}
在 Release
模式下调用它们 int.MaxValue
次产生:
- 12032 毫秒 - 对于
TestWithIndex
- 10525 毫秒 - 对于
TestWithTemp
然后让我们看看生成的 IL( Release模式,启用优化):
TestWithIndex
.method private hidebysig static
int32 TestWithIndex (
int32[] 'array'
) cil managed
{
// Method begins at RVA 0x2564
// Code size 29 (0x1d)
.maxstack 2
.locals init (
[0] int32 x,
[1] int32 y,
[2] int32 z,
[3] int32 CS$1$0000
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: ldelem.i4
IL_0004: ldc.i4.2
IL_0005: mul
IL_0006: stloc.0
IL_0007: ldarg.0
IL_0008: ldc.i4.1
IL_0009: ldelem.i4
IL_000a: ldc.i4.3
IL_000b: mul
IL_000c: stloc.1
IL_000d: ldarg.0
IL_000e: ldc.i4.1
IL_000f: ldelem.i4
IL_0010: ldc.i4.4
IL_0011: mul
IL_0012: stloc.2
IL_0013: ldloc.0
IL_0014: ldloc.1
IL_0015: add
IL_0016: ldloc.2
IL_0017: add
IL_0018: stloc.3
IL_0019: br.s IL_001b
IL_001b: ldloc.3
IL_001c: ret
} // end of method Program::TestWithIndex
这里我们看到三个 ldelem.i4
。
TestWithTemp
.method private hidebysig static
int32 TestWithTemp (
int32[] 'array'
) cil managed
{
// Method begins at RVA 0x2590
// Code size 29 (0x1d)
.maxstack 2
.locals init (
[0] int32 'value',
[1] int32 x,
[2] int32 y,
[3] int32 z,
[4] int32 CS$1$0000
)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: ldelem.i4
IL_0004: stloc.0
IL_0005: ldloc.0
IL_0006: ldc.i4.2
IL_0007: mul
IL_0008: stloc.1
IL_0009: ldloc.0
IL_000a: ldc.i4.3
IL_000b: mul
IL_000c: stloc.2
IL_000d: ldloc.0
IL_000e: ldc.i4.4
IL_000f: mul
IL_0010: stloc.3
IL_0011: ldloc.1
IL_0012: ldloc.2
IL_0013: add
IL_0014: ldloc.3
IL_0015: add
IL_0016: stloc.s CS$1$0000
IL_0018: br.s IL_001a
IL_001a: ldloc.s CS$1$0000
IL_001c: ret
} // end of method Program::TestWithTemp
当然这里只有一个ldelem.i4
。