C# If vs. Switch

Performance optimization

The performance of if and switch is rarely critical. But to increase your understanding of the execution engine, knowing some of the performance details is useful. We compare the performance of if-statements and switch-statements.

If

Warning:These benchmarks are of limited practical use. They are mainly useful when you are trying to determine when to choose switch.

Example

To start, this program declares two methods that are tested. One is called IsValidIf—it implements a selection with several if-statements. The second is called IsValidSwitch—it implements a selection as a switch.

Note:The results of the two methods on all inputs are equivalent—they have the same effects.

And:When this program is executed, the time required per call of each of those methods is reported.

C# program that tests if and switch performance

using System;
using System.Diagnostics;

class Program
{
    static bool IsValidIf(int i)
    {
	// Uses if-expressions to implement selection statement.
	if (i == 0 ||
	    i == 1)
	{
	    return true;
	}
	if (i == 2 ||
	    i == 3)
	{
	    return false;
	}
	if (i == 4 ||
	    i == 5)
	{
	    return true;
	}
	return false;
    }

    static bool IsValidSwitch(int i)
    {
	// Implements a selection statement with a switch.
	switch (i)
	{
	    case 0:
	    case 1:
		return true;
	    case 2:
	    case 3:
		return false;
	    case 4:
	    case 5:
		return true;
	    default:
		return false;
	}
    }

    const int _max = 100000000;
    static void Main()
    {
	bool b;
	var s1 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    b = IsValidIf(i);
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    b = IsValidSwitch(i);
	}
	s2.Stop();
	Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00 ns"));
	Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00 ns"));
	Console.Read();
    }
}

Result: switch faster

3.83 ns [if]
2.88 ns [switch]
One: 1

The if-statement method required an additional 1 nanosecond per method invocation. The switch implementation was faster. If you look at the intermediate code here, you will see that the switch uses a jump table opcode.

And:The if-statement is implemented with conditional branches. The jump table is faster—it requires fewer steps for certain inputs.

Question

It is tempting to think that a switch is always faster than an equivalent if-statement. However, this is not true. A situation where the switch is slower is when the actual runtime of the program has a very skewed distribution of inputs.

Benchmark

So:If the input is almost always a specific value, then using an if-statement to test for that value may be faster.

Example 2

Note

To continue, we look at a benchmark harness that tests two implementations.
Method1 uses,
internally,
a switch statement. And Method2 uses an if-else if construct. The two methods have the same results.

Note:The methods receive the value zero 60% of the time. They receive the value one 40% of the time.

Tip:Method2 is most optimized for the value zero because it tests for it first.

C# program that tests switch and if

using System;
using System.Diagnostics;

class Program
{
    const int _max = 100000000;
    static void Main()
    {
	Method1(0); // JIT.
	Method2(0); // JIT.

	var s1 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    Method1(0);
	    Method1(0);
	    Method1(0);
	    Method1(0);
	    Method1(0);
	    Method1(0);
	    Method1(1);
	    Method1(1);
	    Method1(1);
	    Method1(1);
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < _max; i++)
	{
	    Method2(0);
	    Method2(0);
	    Method2(0);
	    Method2(0);
	    Method2(0);
	    Method2(0);
	    Method2(1);
	    Method2(1);
	    Method2(1);
	    Method2(1);
	}
	s2.Stop();
	Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00 ns"));
	Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000 * 1000) /
	    _max).ToString("0.00 ns"));
	Console.Read();
    }

    static int Method1(int val)
    {
	switch (val)
	{
	    case 0:
		{
		    return 1;
		}
	    case 1:
		{
		    return 3;
		}
	    default:
		{
		    throw new Exception();
		}
	}
    }

    static int Method2(int val)
    {
	if (val == 0)
	{
	    return 1;
	}
	if (val == 1)
	{
	    return 3;
	}
	throw new Exception();
    }
}

Result: if faster

39.81 ns [switch]
18.79 ns [if]
If keyword

We see that the two if-statements perform better. You save around 2 nanoseconds per method call. The intermediate language reveals that the switch-statement uses a "switch" opcode. The if-statements simply use branch opcodes.

Also:The exception logic was added to avoid inlining at the level of the JIT compiler.

JIT Method Test

Summary

In some cases, an equivalent switch statement is slower than an if-statement or chain of if-statements. Using frequency heuristics, you can optimize a fast path with an if-statement in many programs.


C#: Switch