80

I was wondering about the performances of the following implementations of conditional structs in javascript.

Method 1:

 if(id==="camelCase"){
    window.location.href = "http://www.thecamelcase.com";
}else if (id==="jsFiddle"){
    window.location.href = "http://jsfiddle.net/";
}else if (id==="cricInfo"){
    window.location.href = "http://cricinfo.com/";
}else if (id==="apple"){
    window.location.href = "http://apple.com/";
}else if (id==="yahoo"){
    window.location.href = "http://yahoo.com/";
}           

Method 2:

switch (id) {
case 'camelCase':
    window.location.href = "http://www.thecamelcase.com";
    break;
case 'jsFiddle':
    window.location.href = "http://www.jsfiddle.net";
    break;
case 'cricInfo':
    window.location.href = "http://www.cricinfo.com";
    break;
case 'apple':
    window.location.href = "http://www.apple.com";
    break;
case 'yahoo':
    window.location.href = "http://www.yahoo.com";
    break;

}

Method 3

var hrefMap = {
camelCase : "http://www.thecamelcase.com",
jsFiddle: "http://www.jsfiddle.net",
cricInfo: "http://www.cricinfo.com",
apple: "http://www.apple.com",
yahoo: "http://www.yahoo.com"
};
window.location.href = hrefMap[id];

Method 4

window.location.href = {
    camelCase : "http://www.thecamelcase.com",
    jsFiddle: "http://www.jsfiddle.net",
    cricInfo: "http://www.cricinfo.com",
    apple: "http://www.apple.com",
    yahoo: "http://www.yahoo.com"
}[id];

Probably Method 3 and 4 might have almost the same performance but just posting to confirm.

aditya_gaur
  • 3,209
  • 6
  • 32
  • 43
  • Slowest thing here is passing values as strings – Luka Rahne Dec 24 '11 at 13:59
  • 1
    here's a benchmark for it: http://jsben.ch/#/o0UDx – EscapeNetscape Oct 19 '16 at 14:31
  • 7
    Micro-optimization: So many things happen in a browser like js compilation, reflows, repaints and others that none of these affects performance. It's like to try to minimize a millimeter of a meter, still, you have one meter, it just wastes time and corrupt mind. I suggest to chose the most beautiful code according to environments, for example, you can not use mapping for object methods unless you use bind. And for optimization, you better use chrome performance tools yo find real bottlenecks and be sure you will find serious issues that you didn't even think of. – Ali Jun 30 '17 at 15:22

4 Answers4

76

According to this JSBen.ch test, the switch setup is the fastest out of the provided methods (Firefox 8.0 and Chromium 15).

Methods 3 and 4 are slightly less fast, but it's hardly noticeable. Clearly, the if-elseif method is significantly slower (FireFox 8.0).

The same test in Chromium 15 does not show significant differences in performance between these methods. In fact, the if-elseif method seems to be the fastest method in Chrome.

Update

I have run the test cases again, with 10 additional entries. The hrefmap (methods 3 and 4) show a better performance.

If you want to implement the compare method in a function, method 3 would definitely win: Store the map in a variable, and refer to this variable at a later point, instead of reconstructing it.

Community
  • 1
  • 1
Rob W
  • 341,306
  • 83
  • 791
  • 678
  • Yeah. The results seem to be almost similar to mine. But will they vary if the number of cases increase drastically? – aditya_gaur Dec 24 '11 at 14:18
  • I've scaled the test, and 3 and 4 are definitely winning: http://jsperf.com/performance-of-assigning-variables-in-javascript/2 – Rob W Dec 24 '11 at 14:25
  • 4
    Besides, you won't get any noticeable performance gain between any of these methods in real life and method 3 is much more readable, easier to change at a later stage and the effects are well separated from the conditions/data. So it's win-win. – juandopazo Dec 24 '11 at 14:31
  • I have done the test using FF 56.0 64bit and method 1 is the fastest. The mapper was really slow compare to other methods. Something wrong with FF ? – Below the Radar Oct 04 '17 at 13:35
  • 1
    With Chrome 62 and this [improved script](http://jsben.ch/3SRWx) (creation of map just once), I do not see any consistent or significant difference between methods 1 to 3. – mhchem Nov 20 '17 at 18:34
  • 1
    I think the test is flawed. The object map should be created during benchmark setup and not part of the benchmark timing, because in the real world it would be used as a singleton / defined once and reused. Doing that shows that mapper is the clear winner: http://jsben.ch/5L2sG – CMcClymont Apr 02 '19 at 01:14
  • In addition to what @Cm – olejorgenb Mar 07 '21 at 23:47
  • @juandopazo it's less win-win if you have actual *conditional logic*, not just simple lookups. See https://stackoverflow.com/a/66961351/8910547 – Inigo Apr 06 '21 at 00:38
  • @CMcClymont i agree the test was flawed. But in more ways than you mention. The mapper is not the clear winner if you do something more than simple lookups of a static values (which is what maps are designed for!). See See https://stackoverflow.com/a/66961351/8910547 – Inigo Apr 06 '21 at 00:40
18

You can always do a jsPerf test yourself. However, in general a lookup table is the fastest way to access data. That would be (3) in your snippets. Also, switch/case is almost always faster than if-else. So the order for your example would be

(3) -> (4) -> (2) -> (1)

Sagar V
  • 12,158
  • 7
  • 41
  • 68
jAndy
  • 231,737
  • 57
  • 305
  • 359
  • In many languages, switch statements are translated into lookup tables by the compiler, so I'd actually expect the latter to be the fastest in those cases. Not sure what browsers do with JS though. – Ohad Schneider Mar 17 '15 at 17:42
  • http://stackoverflow.com/questions/395618/is-there-any-significant-difference-between-using-if-else-and-switch-case-in-c/395965#395965 – Ohad Schneider Mar 17 '15 at 17:44
2

Performance diverges for conditional logic (rather than mere value lookup)

if-else vs switch vs map of functions vs class method dispatch

I think a lot of people come to this question, Performance of if-else, switch or map based conditioning, because they want to know how best to condition logic, as the title implies, rather than simple key-based value lookup.

My benchmark differs from the one in the accepted answer and also corrects a number of its flaws (further explanation at bottom below results table):

  1. Tests branched logic. i.e. conditional execution flow, not simple lookups.

  2. Branches randomly. A random sequence of branch keys is generated in setup. Each approach is then tested with the same sequence.

  3. Branch results aren't predictable. The logic result for each branch are not the same for other branches, nor are they the same for subsequent executions of the same branch.

  4. There are 11 branches. To me this question is more relevant to around that many. If there are much fewer, it doesn't make sense to consider anything other than if-else or switch.

  5. Re-used structures are initialized in setup rather than in the benchmarked code block.

This is what I got on Safari/macOS:

approach JSBench
if-else 100
switch 99+
map of functions ~90
class method dispatch ~85

I ran the same benchmark again with twice as many branches (22) expecting to see map to gain ground, and I got about the same results (though class method dispatch may be doing slightly relatively better). If I had time I'd write code to generate benchmark code so that I could graph a wide range of branch counts... but alas I don't.

Limitations in the question's sample code and benchmarks in the other answers and comments

The question's own sample code as well as the benchmarks code used in Rob W's answer and jAndy's answer only test value lookup. As expected, for a small set of keys those benchmarks show negligible performance differences; Any significant difference would have been a flaw in the JS engine. They do not demonstrate the issue of conditional logic.

In addition, as some have pointed out, there are other flaws in the benchmark code:

  • Performance only matters if the conditional logic is executed thousands of times. In such cases one would not reinitialize data structures each use.

  • The test code takes the same branch every time. This has two problems:

    • It does not reflect average cost (e.g. for an if-else or switch, earlier branches are cheaper, later are more expensive).

    • Compile-time or JIT optimization is likely to optimize it away, thereby producing misleading results (because in real code, the conditions would not be so predictable).

  • Each branch produces exactly the same result each time. And for the Rob W's benchmark, the result is the same as the input!

    • Of course a map will perform well for this usage. That's what they are designed for!

    • If you have conditional logic where the logic for each branch produced the exact same result each time, you should consider using memoization.

Inigo
  • 12,186
  • 5
  • 41
  • 70
-1

Just thought I'd add this as a possible consideration. I came across this doing research on this very question... http://davidbcalhoun.com/2010/is-hash-faster-than-switch-in-javascript

It takes different engines and browsers into account.

Ubermonk
  • 101
  • 1
  • 8
  • 5
    Just posting a link is not helpful. Should add relevant content from the link over here. – Champ Mar 02 '16 at 16:41