首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用数组索引的C#性能

使用数组索引的C#性能
EN

Stack Overflow用户
提问于 2014-01-13 19:57:16
回答 3查看 894关注 0票数 5

我有一个数组,我想在同一个方法中多次使用单个值。

代码语言:javascript
复制
int[] array = new array[] {1, 2, 3};

现在我问您,如果使用数组和索引来获得值,这是否是一个很大的性能问题.

代码语言:javascript
复制
int x = array[1] * 2;
int y = array[1] * 3;
int z = array[1] * 4;

还是创建一个局部变量更好?

代码语言:javascript
复制
int value = array[1];
int x = value * 2;
int y = value * 3;
int z = value * 4;

我知道用局部变量更容易阅读,但它只是让我感兴趣的是,它是否会造成性能上的差异。;-)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-13 20:15:36

虽然我同意这样的微优化是有害的和不必要的,并且可读性可能更重要的,但是为两种方法做一个虚拟基准是相当有趣的:

代码语言:javascript
复制
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时间会产生:

  • 12032 ms -用于TestWithIndex
  • 10525 ms -用于TestWithTemp

然后让我们看一下IL生成的(释放模式,启用优化):

TestWithIndex

代码语言:javascript
复制
.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

代码语言:javascript
复制
.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

票数 3
EN

Stack Overflow用户

发布于 2014-01-13 19:59:21

不,没有表现上的差别。要做到这一点:

代码语言:javascript
复制
int x = array[1] * 2;

无论如何,在生成IL时,array[1]上的值必须移动到内存位置。剩下的操作将由编译器优化(也就是说,它不会多次检索值)。

好的,为了解决这个争论,我决定把每个人都甩了,下面是第一个:

代码语言:javascript
复制
.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

下面是第二个:

代码语言:javascript
复制
.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

它们完全一样--正如我所说的。

票数 2
EN

Stack Overflow用户

发布于 2014-01-13 20:25:23

如果您没有性能要求或性能问题,那么您的主要目标是编写易于维护的可读代码。在第一个示例中很容易看到重复:

代码语言:javascript
复制
int x = array[1] * 2;
int y = array[1] * 3;
int z = array[1] * 4;

它有几个问题。首先,你有越多的重复代码,你必须支持的代码越多,你就越有可能不会在某个时候修改一个代码副本。第二,复制总是意味着代码中有隐藏的知识。如果某些代码被重复,那么它就有特定的含义,这一点您还没有说清楚。例如,在数组的第二项中有速度值。使这一知识明确:

代码语言:javascript
复制
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%,然后再进行优化(如果它们确实需要的话)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21100228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档