使用数组索引的 C# 性能

标签 c# arrays performance

<分区>

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

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

关于使用数组索引的 C# 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21100228/

相关文章:

c# - 如何将对象转换为强类型 XML

c# - SAP Crystal reports(无法加载数据库信息)

c# - 处理可能引发多个异常的方法中的异常

python - Numba 函数比 C++ 慢,循环重新排序进一步减慢 x10

r - 字符串分解

c# - Azure 服务总线未检测到重复项

php - 如何将数组键名称与另一个数组键名称匹配

javascript - 将表单结果传递到另一个表单并转换为表单值

javascript - 将数组中的多个元素移动到数组中的某个索引

MYSQL Performance on subquery count of another table