我有一个数组,我想在同一个方法中多次使用单个值。
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;我知道用局部变量更容易阅读,但它只是让我感兴趣的是,它是否会造成性能上的差异。;-)
发布于 2014-01-13 20:15:36
虽然我同意这样的微优化是有害的和不必要的,并且可读性可能更重要的,但是为两种方法做一个虚拟基准是相当有趣的:
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;
}在int.MaxValue模式下将它们称为Release时间会产生:
TestWithIndexTestWithTemp然后让我们看一下IL生成的(释放模式,启用优化):
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。
发布于 2014-01-13 19:59:21
不,没有表现上的差别。要做到这一点:
int x = array[1] * 2;无论如何,在生成IL时,array[1]上的值必须移动到内存位置。剩下的操作将由编译器优化(也就是说,它不会多次检索值)。
好的,为了解决这个争论,我决定把每个人都甩了,下面是第一个:
.method private hidebysig static void Main(string[] args) cil managed
{
IL_0000: nop
IL_0001: ldc.i4.3
IL_0002: newarr [mscorlib]System.Int32
IL_0007: dup
IL_0008: ldtoken field valuetype '<PrivateImplementationDetails>{79A4FD92-FA37-4EB9-8056-B52A57262FBB}'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>{79A4FD92-FA37-4EB9-8056-B52A57262FBB}'::'$$method0x6000001-1'
IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0012: stloc.0
IL_0013: ldloc.0
IL_0014: ldc.i4.1
IL_0015: ldelem.i4
IL_0016: stloc.1
IL_0017: ldloc.1
IL_0018: ldc.i4.2
IL_0019: mul
IL_001a: stloc.2
IL_001b: ldloc.1
IL_001c: ldc.i4.3
IL_001d: mul
IL_001e: stloc.3
IL_001f: ldloc.1
IL_0020: ldc.i4.4
IL_0021: mul
IL_0022: stloc.s z
IL_0024: ret
} // end of method Program::Main下面是第二个:
.method private hidebysig static void Main(string[] args) cil managed
{
IL_0000: nop
IL_0001: ldc.i4.3
IL_0002: newarr [mscorlib]System.Int32
IL_0007: dup
IL_0008: ldtoken field valuetype '<PrivateImplementationDetails>{79A4FD92-FA37-4EB9-8056-B52A57262FBB}'/'__StaticArrayInitTypeSize=12' '<PrivateImplementationDetails>{79A4FD92-FA37-4EB9-8056-B52A57262FBB}'::'$$method0x6000001-1'
IL_000d: call void [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array,
valuetype [mscorlib]System.RuntimeFieldHandle)
IL_0012: stloc.0
IL_0013: ldloc.0
IL_0014: ldc.i4.1
IL_0015: ldelem.i4
IL_0016: stloc.1
IL_0017: ldloc.1
IL_0018: ldc.i4.2
IL_0019: mul
IL_001a: stloc.2
IL_001b: ldloc.1
IL_001c: ldc.i4.3
IL_001d: mul
IL_001e: stloc.3
IL_001f: ldloc.1
IL_0020: ldc.i4.4
IL_0021: mul
IL_0022: stloc.s z
IL_0024: ret
} // end of method Program::Main它们完全一样--正如我所说的。
发布于 2014-01-13 20:25:23
如果您没有性能要求或性能问题,那么您的主要目标是编写易于维护的可读代码。在第一个示例中很容易看到重复:
int x = array[1] * 2;
int y = array[1] * 3;
int z = array[1] * 4;它有几个问题。首先,你有越多的重复代码,你必须支持的代码越多,你就越有可能不会在某个时候修改一个代码副本。第二,复制总是意味着代码中有隐藏的知识。如果某些代码被重复,那么它就有特定的含义,这一点您还没有说清楚。例如,在数组的第二项中有速度值。使这一知识明确:
int speed = array[1];
int x = speed * 2; // of course, magic numbers also should be replaced
int y = speed * 3;
int z = speed * 4;记住-过早的优化是邪恶的。通常,您有20%的代码,这需要80%的执行时间。您的优化很有可能不会影响应用程序性能。因此,您应该首先找到这20%,然后再进行优化(如果它们确实需要的话)。
https://stackoverflow.com/questions/21100228
复制相似问题