8

I've google'd a bit but I still feel to be lost. I am writing a CPU emulator in JavaScript (namely Z80 in me case, currently). There is a huge switch statement in its heart. Though I can run some benchmarks of course, I can't be sure about future JavaScript engines of different browsers (ok, nobody can be, I know, but somebody should have greater knowledge of javascript engines of different browsers here than me ...).

Is it faster to use other constructs than switch statement? Like an array of functions, etc. Also similar problem: I have the situation to have possible prefixed Z80 opcodes. Some 'case' branches of the switch needs another switch inside, but not all. I am thinking to convert the whole stuff into an even bigger (but only one level "deep") switch construct to have opcodes between 0-255 as normal, 256-511 as 0xDD prefixed etc, some of them would have more 'case's (without break) for the single same code. Or should I avoid big switch statements as much as possible even for the base opcode table (256 'case' branches)?

For C code, compiler would create a jump table in this situation which is quite fast. But what's about javascript?

Another similar question: is it worth to have a switch statement with only two 'case' branches and a 'default' entry, or it's really the situation where if ... else is better?

It can be important to declare that I use only numeric (and integer - though it does not mean too much in JavaScript since AFAIK it only has one numeric type) values in my switch constructs.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
LGB
  • 728
  • 1
  • 9
  • 20
  • 3
    `Though I can run some benchmarks of course`, sounds like a good place to start – Matt Burland Sep 16 '13 at 14:35
  • 2
    You can benchmark some of that here: http://jsperf.com/switch-if-else/10 Arrays/objects of functions accessed by key word are worth exploring. –  Sep 16 '13 at 14:37
  • Similar question six years later: https://stackoverflow.com/questions/59557414/why-is-node-10x-slower-than-chrome/ – Lawrence Kesteloot Jan 02 '20 at 22:29

4 Answers4

7

The switch is at least as fast as having to evaluate many ifs and elses. Even without knowing the insides of JavaScript engines and optimizers, this we know for sure.

In case of an interpreter such as your case, it might be even better to store functions in a dictionary (array) instead, and do a binary lookup of your code in that array.

So create an array with the code you would put in the cases as index and JavaScript code (functions) as values, and just execute the code you find at the array.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
  • 2
    Ok, thanks! According to my stupid benchmark (using 256 cases) array of functions is more than ten times faster (google chrome 30) than a switch-case statement. It seems my C background always misleads me. – LGB Sep 16 '13 at 15:34
  • 22
    @LGB actually in V8 (JS engine used by google chrome) you need to jump through a lot of hoops to get switch case optimized: All the cases must be of same type. All the cases must either be string **literals** or 31-bit signed integer **literals**. And there must be less than 128 cases. And even after all those hoops, all you get is what you would have gotten with if-elses anyway (I.E. no jump tables or sth like that). True story. – Esailija Sep 17 '13 at 05:42
  • 7
    References: [Same type](https://github.com/v8/v8/blob/596d0ce7b7a3900c529025aaa77e5fc39162c8c5/src/hydrogen.cc#L3359), [31-bit signed integer **literals**](https://github.com/v8/v8/blob/596d0ce7b7a3900c529025aaa77e5fc39162c8c5/src/hydrogen.cc#L3404), [string **literals**](https://github.com/v8/v8/blob/596d0ce7b7a3900c529025aaa77e5fc39162c8c5/src/hydrogen.cc#L3373), [128 max](https://github.com/v8/v8/blob/596d0ce7b7a3900c529025aaa77e5fc39162c8c5/src/hydrogen.cc#L3350) – Esailija Sep 17 '13 at 05:48
  • 3
    @LGB just look at the code you get when one jumps through all those hoops http://pastebin.com/Xu3igduJ and even have consecutive integers. – Esailija Sep 17 '13 at 07:57
  • @Esailija thank you for that pointer, it helped me in this question: https://stackoverflow.com/questions/59557414/why-is-node-10x-slower-than-chrome/ – Lawrence Kesteloot Jan 02 '20 at 22:28
3

switch is clearly going to be faster than if-else, since it runs in constant time, only requiring a single lookup. The ambiguous case might be for lookup tables.

I've modified an existing test-case for jsperf for you to compare:

http://jsperf.com/if-switch-lookup-table/18

The lookup table implementation is the fastest of the three.

simonzack
  • 19,729
  • 13
  • 73
  • 118
1

Switch is much slower than map lookup in all modern browsers when there are many cases to check. See the benchmarks:

Finesse
  • 9,793
  • 7
  • 62
  • 92
0

At around 1000 iterations and random sampling, if and switch bounce around each other. The difference varies about 5% to 15%. It probably wouldn't be noticeable. When you bump that up to 100000, then switch always wins, by around the same %. That's to be expected, since switch reads once and compares against many, while if reads many and compares against many.

But what is noticeable is using a new Map() object to find a result completely blows away either of them.

https://jsperf.com/get-speed-comparison

ShortFuse
  • 5,970
  • 3
  • 36
  • 36