首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >开关似乎比如果

开关似乎比如果
EN

Stack Overflow用户
提问于 2012-12-30 06:32:53
回答 4查看 1.7K关注 0票数 12

我对switch上的速度很好奇,认为它“非常”快,但我有一个测试用例,它似乎表明一个开关大约和4个if测试一样快,而我预计(没有确凿的理由)它会和一个测试一样快。下面是我为比较switchif而编写的两种方法

代码语言:javascript
运行
复制
public static int useSwitch(int i) {
    switch (i) {
        case 1: return 2;
        case 2: return 3;
        case 3: return 4;
        case 4: return 5;
        case 5: return 6;
        case 6: return 7;
        default: return 0;
    }
}

public static int useIf(int i) {
    if (i == 1) return 2;
    if (i == 2) return 3;
    if (i == 3) return 4;
    if (i == 4) return 5;
    if (i == 5) return 6;
    if (i == 6) return 7;
    return 0;
}

这是我的测试代码:

代码语言:javascript
运行
复制
long x = 0;
for (int i = 0; i < 999999; i++)
    x += useIf(i % 7); // I use "x" so calls won't get optimized out

useSwitch()的另一个相同的循环

在我的机器上,这些循环几乎是同时完成的,这是一个惊喜。

我得出的ifs数为"4",因为这是给定输入范围的平均值(我认为)。

如果我减少逻辑选项的数量,那么if版本的速度明显更快。

我的问题是:

switch实际上没有那么快,还是在某种程度上这是一个“不公平”的测试?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-12-30 07:30:12

这在某种程度上是不公平的。大部分CPU时间将用于处理模块操作:i % 7。Modulo --即使是在最新的最大型CPU上--也非常慢,执行起来可能比正在尝试测试的if()或switch()实现要长20倍。

此外,有两种不同的方法可以优化开关语句。一种是查找表,它用于像您提出的那种顺序的情况。另一种方法是在适当的情况下使用搜索分区树。当情况稀疏时,就会发生这种情况,如下面的示例:

代码语言:javascript
运行
复制
switch (someInt) {
    case 0:  ... break;
    case 10:  ... break;
    case 102:  ... break;
    case 6543:  ... break;
    case 19303:  ... break;
    case 19305:  ... break;
    // and so forth...
}

大多数编译器将使用一个未展开的分区树来找到正确的大小写,在长开关上,这会提供非常好的avg和最坏情况下的跳转来找到正确的情况。生成的伪代码如下所示:

代码语言:javascript
运行
复制
if (someInt >= 6543) {
    if (someInt >= 19303) {
        // continue tree search, etc.
    }
    else if (someInt==6543) {}
}
else if (someInt >= 0) {
    if (someInt >= 10) {
        // continue tree search, etc.
    }
    else if (someInt == 0) {} 
}
else {
    // default case handler...
}

正如这里所示,对于6-8个案例来说,这并没有多大帮助,但是如果您切换了一个可能是50+的案例,那么它将是非常有用的。线性搜索将有O(n) (50个条件最差,25个avg),而分区树版本将接近sqrt(n) (8-9个条件最差,5-7个avg,取决于编译器的选择)。

票数 15
EN

Stack Overflow用户

发布于 2012-12-30 07:02:52

开关应该更快,只要看看字节码就够了

代码语言:javascript
运行
复制
   TABLESWITCH
      1: L1
      2: L2
      3: L3
      4: L4
      5: L5
      6: L6

以确保这是一项特殊的行动。在现实生活中,由于JVM的优化,可能没有什么不同。但是如果我们用-Xint (interepret模式)运行您的代码,那么差别应该很明显,在我的PC上,它是63比93 (ms),赞成切换。

票数 5
EN

Stack Overflow用户

发布于 2012-12-30 06:49:38

这里有趣的问题是编译器如何翻译开关(可能像哈希表,或者结果可以类似于if-else结构)。它还可以根据输入进行各种优化(如果已知的话)。但是,这是编译器依赖的,我知道的任何规范中都没有定义。

所以,我不能给你答案,但我可以告诉你,如果你想改进你的测试,你可以给它输入7。这将使它通过所有的测试,直到返回一个答案,如果开关是优化的,它会给你更好的结果,如果它是一个假设-如果它会有相似的结果。只是不要硬编码7,这样编译器就不会提前知道它,使用parseint之类的方法从字符串中获取它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14088824

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档