数组#Contain与OR逻辑与switch语句的性能

本文关键字:语句 switch 性能 #Contain OR 数组 | 更新日期: 2023-09-27 17:59:41

其中哪个最快,哪个最慢(C#)?

// Array#Contain
int i = ...;
if ((new int[] { 0, 1, 3, 7, ... }).Contains(i))
{
  ...
}
// OR logic
int i = ...;
if (i == 0 || i == 1 || i == 3 || i == 7  || ...)
{
  ...
}
// switch statement
int i = ...;
switch(i)
{
  case 0:
  case 1:
  case 3:
  case 7:
  ...
    ...
    break;
}

数组#Contain与OR逻辑与switch语句的性能

这些东西的性能取决于目标机器体系结构,可能还取决于操作系统
对于x86/x64机器,我认为上面的代码应该由JIT翻译成以下等效的汇编程序:

  1. Array.Contains方法

    lea    EDI, [...]
    mov    ECX, sizeof(...)
    repne  scasd
    
  2. if语句中的顺序ORs

    mov    EAX, ...
    cmp    EAX, 0
    jz     iftrue
    cmp    EAX, 1
    jz     iftrue
    cmp    EAX, 3
    jz     iftrue
    ...
    jmp    endif
    iftrue:
    ...
    endif:
    
  3. switch语句

    lea    EBX, [case_values_table]
    xor    EAX, EAX
    mov    AL, case_index
    xlat
    mov    ESI, EAX
    jmp    [case_codeblocks_table][ESI * 4 or 8]
    

您只需要对每个选项的ASM指令的时序求和,包括由于清除操作码预取队列的正概率,任何jmp s的潜在缺点。

但我相信,更好的建议是选择最受支持的C#代码

我不确定,但我希望switch语句是最快的,因为这里解释的原因,即通过作为哈希表的实现(对于超过5项的case语句),查找时间恒定。

为一个.Contains创建一个新的int[]似乎效率很低,但您可以使用常量字段来解决这个问题。此外,该方法必须在所有元素上迭代(最坏的情况),因此它可能是性能方面最不有利的选项。

if级联可能会击败开关if,因为在几乎所有情况下,第一个条件都是正确的,因为在确定之后它不必评估任何东西。

话虽如此,我通常会使用数组,因为它读起来很好,而且很容易更改。性能的提高通常是没有意义的。