Skip to main content
2 of 4
added 112 characters in body
user avatar
user avatar

If we're just talking about pure performance and tossing aside all notions of productivity and maintainability, then it's hard to beat a switch statement.

It's potentially even faster than a jump table, at least on the C++ side (I imagine C# optimizers are pretty smart too). I was surprised one time looking through some disassembly in Godbolt for a switch statement like so:

switch (opcode)
{
case 0x01:
    call_some_function_which_calls_other_functions(...);
    break;
case 0x2:
    ...
}

Only to get a moment where I was extremely confused. Where's the jump table? Then the confusion was followed by a moment of awe. Instead of using a jump table, the optimizer actually figured out that the entire switch and nest of function calls can boil down to a simple LUT. It turned the analogical equivalent above to something completely branchless like:

data = some_other_data[opcode];

And I was so impressed because I never even conceived that that whole mess of switch statements and nested function calls with parameters being passed could boil down to a simple assignment from a look-up table of data. I then looked through all the code and function calls and realized, "Hey, actually you could just use a LUT here." So what an optimizer can do with some switch statements and nested function calls which it knows ahead at compile-time is pretty amazing. I haven't been quite as amazed yet when virtual dispatch is involved, though polymorphism often yields code that's so much easier to maintain and looks so much nicer.

Also while it is kinda gross, there can actually be cases where you need to branch off 100+ different conditions in a real-world scenario. A prime example I've looked at is an emulator which has to deal with a boatload of opcodes for the target hardware which supported an instruction set that contained 100 instructions or more.

So I generally think whatever you do, you have to provide the optimizer with as much information it can know in advance at compile-time as possible. The switch statement achieves that. Not all optimizers are so smart at figuring out in advance where a function call involving dynamic dispatch (virtual function, function pointer, etc) will ultimately lead to at compile-time.

user204677