If vs. Switch Speed

C#PerformanceSwitch StatementIf Statement

C# Problem Overview


Switch statements are typically faster than equivalent if-else-if statements (as e.g. descibed in this article) due to compiler optimizations.

How does this optimization actually work? Does anyone have a good explanation?

C# Solutions


Solution 1 - C#

The compiler can build jump tables where applicable. For example, when you use the reflector to look at the code produced, you will see that for huge switches on strings, the compiler will actually generate code that uses a hash table to dispatch these. The hash table uses the strings as keys and delegates to the case codes as values.

This has asymptotic better runtime than lots of chained if tests and is actually faster even for relatively few strings.

Solution 2 - C#

This is a slight simplification as typically any modern compiler that encounters a if..else if .. sequence that could trivially be converted into a switch statement by a person, the compiler will as well. But just to add extra fun the compiler is not restricted by syntax so can generate "switch" like statements internally that have a mix of ranges, single targets, etc -- and they can (and do) do this for both switch and if..else statements.

Anyhoo, an extension to Konrad's answer is that the compiler may generate a jump table, but that's not necessarily guaranteed (nor desirable). For a variety of reasons jump tables do bad things to the branch predictors on modern processors, and the tables themselves do bad things to cache behaviour, eg.

switch(a) { case 0: ...; break; case 1: ...; break; }

If a compiler actually generated a jump table for this it would likely be slower that the alternative if..else if.. style code because of the jump table defeating branch prediction.

Solution 3 - C#

The no-match stats may not be good.

If you actually download the source, the no match values are known to be 21, in both the if and switch case. A compiler should be able to abstract away, knowing which statement should be run at all times, and a CPU should be able to branch predict properly.

The more interesting case is when not every case breaks, in my opinion, but that may not have been the scope of the experiment.

Solution 4 - C#

Switch/case statements may be typically faster 1-level deep, but when you start getting into 2 or more, switch/case statements start taking 2-3 times as long as nested if/else statements.

[This article has some speed comparisons][1] highlighting the speed differences when such statements are nested.

For example, according to their tests, sample code like the following:

if (x % 3 == 0)
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;
        else if (x % 3 == 1)
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;
        else if (x % 3 == 2)
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;
        else
            if (y % 3 == 0)
                total += 3;
            else if (y % 3 == 1)
                total += 2;
            else if (y % 3 == 2)
                total += 1;
            else
                total += 0;

finished in half the time the equivalent switch/case statement took to run:

switch (x % 3)
    {
        case 0:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
        case 1:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
    case 2:
            switch (y % 3)
            {
                case 0: total += 3;
                    break;
                case 1: total += 2;
                    break;
                case 2: total += 1;
                    break;
                default: total += 0;
                    break;
            }
            break;
    default:
        switch (y % 3)
        {
            case 0: total += 3;
                break;
            case 1: total += 2;
                break;
            case 2: total += 1;
                break;
            default: total += 0;
                break;
        }
        break;
    }

Yeah it's a rudimentary example, but it illustrates the point.

So a conclusion might be use switch/case for simple types that are only one level deep, but for more complex comparisons and multiple nested levels use the classic if/else constructs?

[1]: http://cc.davelozinski.com/c-sharp/what-is-the-fastest-conditional-statement "http://cc.davelozinski.com/c-sharp/what-is-the-fastest-conditional-statement"

Solution 5 - C#

The only advantage of the if over case is when there is a noticeable increase of occurrence frequency of the first case.

Not sure exactly where the threshold is, but I use case syntax unless the first "almost always" passes the first test.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDirk VollmarView Question on Stackoverflow
Solution 1 - C#Konrad RudolphView Answer on Stackoverflow
Solution 2 - C#olliejView Answer on Stackoverflow
Solution 3 - C#CalythView Answer on Stackoverflow
Solution 4 - C#user3810913View Answer on Stackoverflow
Solution 5 - C#RalphView Answer on Stackoverflow