if-else,switch或基于map的条件的性能

时间:2011-12-24 13:52:24

标签: javascript switch-statement if-statement

我想知道javascript中以下条件结构实现的性能。

方法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/";
}           

方法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;

}

方法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];

方法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];

可能方法3和4可能具有几乎相同的性能,但只是发布以确认。

4 个答案:

答案 0 :(得分:60)

根据此JSBen.ch测试,switch设置是所提供方法中最快的(Firefox 8.0和Chromium 15)。

方法3和方法4的速度稍慢,但几乎不可察觉。显然,if-elseif方法明显变慢(FireFox 8.0)。

在Chromium 15中的相同测试未显示这些方法之间的性能的显着差异。事实上,if-elseif方法似乎是Chrome中最快的方法。

更新

我已运行测试用例again,另外还有10个条目。 hrefmap(方法3和4)显示出更好的性能。

如果你想在函数中实现compare方法,方法3肯定会胜出:将地图存储在一个变量中,稍后再引用这个变量,而不是重建它。

答案 1 :(得分:16)

您可以随时自行进行jsPerf测试。但是,通常查找表是访问数据的最快方式。在你的片段中,这将是(3)。此外,switch/case几乎总是比if-else更快。所以你的例子的顺序是

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

答案 2 :(得分:0)

条件逻辑的性能发散(而不仅仅是值查找)

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

我想很多人都会问这个问题,基于 if-else、switch 或 map 的调节的性能,因为他们想知道如何最好地调节 逻辑 ,正如标题所暗示的,而不是简单的基于键的值查找。

My benchmark 与已接受答案中的不同,还纠正了一些缺陷(结果表底部的进一步解释):

  1. 测试分支逻辑。即条件执行流程,而不是简单的查找。

  2. 随机分支。在设置中生成随机的分支密钥序列。然后用相同的顺序测试每种方法。

  3. 分支结果不可预测。每个分支的逻辑结果对于其他分支是不一样的,对于同一个分支的后续执行也不一样。

  4. 有 11 个分支。对我来说,这个问题与那么多人更相关。如果数量少得多,则考虑除 if-elseswitch 之外的任何其他内容都没有意义。

  5. 重用的结构在设置中初始化,而不是在基准代码块中。

这是我在 Safari/macOS 上得到的:

<头>
方法 JSBench
if-else 100
switch 99+
map of functions ~90
class method dispatch ~85

我运行 same benchmark again with twice as many branches (22) 时希望看到地图取得进展,但得到了大致相同的结果(尽管 class method dispatch 的表现可能相对稍好一些)。如果我有时间,我会编写代码来生成基准代码,这样我就可以绘制各种分支计数的图表……但可惜我没有。

问题示例代码的限制以及其他答案和评论中的基准

问题自己的示例代码以及 Rob W's answerjAndy's answer 中使用的基准代码仅用于测试值查找。正如预期的那样,对于一小组键,这些基准测试显示的性能差异可以忽略不计;任何显着差异都是 JS 引擎的缺陷。他们没有证明条件逻辑的问题。

此外,正如一些人指出的,基准代码中还有其他缺陷:

  • 仅当条件逻辑执行数千次时,性能才重要。在这种情况下,不会每次使用都重新初始化数据结构。

  • 测试代码每次都采用相同的分支。这有两个问题:

    • 它不反映平均成本(例如,对于 if-else 或 switch,较早的分支更便宜,后来更昂贵)。

    • 编译时或 JIT 优化可能会将其优化掉,从而产生误导性的结果(因为在实际代码中,条件不会那么可预测)。

  • 每个分支每次都产生完全相同的结果。而对于Rob W's benchmark,结果与输入相同!

    • 当然,地图对于这种用法会表现得很好。这就是它们的设计目的!

    • 如果您有条件逻辑,其中每个分支的逻辑每次都产生完全相同的结果,您应该考虑使用 memoization

答案 3 :(得分:-1)

我想我会加上这个作为一个可能的考虑因素。我在这个问题上进行了研究...... http://davidbcalhoun.com/2010/is-hash-faster-than-switch-in-javascript

需要考虑不同的引擎和浏览器。