3

Which of these is the fastest and which is the slowest (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;
}
drew.cuthbert
  • 1,005
  • 1
  • 9
  • 21
  • 10
    You could very easily benchmark them – Ayush Apr 24 '14 at 07:46
  • 4
    Use the one that is easiest to maintain. You've lost your effectiveness the moment you started micro optimization. – Tarec Apr 24 '14 at 07:50
  • @xbonez to be honest, I don't know how to do that. Could you advise? – drew.cuthbert Apr 24 '14 at 07:51
  • @Tarec thanks for the comment, I totally agree. This was just something I thought of that made me curious. Mostly about the performance of Array#Contain (which I think is easiest to maintain) vs the other two. – drew.cuthbert Apr 24 '14 at 07:52
  • 2
    My 2 cents, besides an array being easier in maintenance if the number of values increase, it is easer to port to a parameter or separate variable at a later stage, and with TPL, the check could be ported to parallel checking for large arrays. So arrays would be my choice (at least for many entries) – Me.Name Apr 24 '14 at 07:56
  • +1 for a great point about TPL @Me.Name, I hadn't thought of that at all. – drew.cuthbert Apr 24 '14 at 08:05

2 Answers2

2

Performance of these things depends on the target machine architecture and maybe OS.
For the x86/x64 machines, I believe the code above should be translated by JIT to the following assembler equivalents:

  1. Array.Contains method

    lea    EDI, [...]
    mov    ECX, sizeof(...)
    repne  scasd
    
  2. Sequental ORs in if statement

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

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

The only thing you need is to sum timings of the ASM instructions for each option, including potential disadvantage of any jmps due to the positive probability of clearing the opcode prefetching queue.

But I believe, that the much better advice is to choose the most supportable C# code.

Dmitry
  • 13,797
  • 6
  • 32
  • 48
-2

I do not know for sure, but I would expect the switch-statement to be the fastest for the reason explained here, i.e. constant lookup time through implementation as a hashtable (for case statements with more than 5 items, that is).

Creating a new int[] for one .Contains seems very inefficient, but you might work around that with a constant field. Also, the method will have to iterate over all elements (worst case), so it is probably the least favorable option performance wise.

The if cascade might beat switch if in almost every case the first condition is correct, since it won't have to evaluate anything after that has been determined.

That being said, I'd usually go with an array, just because it reads nicely and is easily changed. The performance gains are usually moot.

Community
  • 1
  • 1
Janis F
  • 2,637
  • 1
  • 25
  • 36
  • 2
    Are you confusing linear with constant? – Joey Apr 24 '14 at 07:50
  • Why would you think that `switch` statement or `Contains` method needs to iterate over all elements? – Tarec Apr 24 '14 at 09:41
  • Switch statement absolutely does not, and I do not state that in my answer (quite the contrary). As for the method, you're right, I do not know the implementation details, please enlighten me. – Janis F Apr 24 '14 at 09:43