我对switch上的速度很好奇,认为它“非常”快,但我有一个测试用例,它似乎表明一个开关大约和4个if测试一样快,而我预计(没有确凿的理由)它会和一个测试一样快。下面是我为比较switch和if而编写的两种方法
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;
}这是我的测试代码:
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实际上没有那么快,还是在某种程度上这是一个“不公平”的测试?
发布于 2012-12-30 07:30:12
这在某种程度上是不公平的。大部分CPU时间将用于处理模块操作:i % 7。Modulo --即使是在最新的最大型CPU上--也非常慢,执行起来可能比正在尝试测试的if()或switch()实现要长20倍。
此外,有两种不同的方法可以优化开关语句。一种是查找表,它用于像您提出的那种顺序的情况。另一种方法是在适当的情况下使用搜索分区树。当情况稀疏时,就会发生这种情况,如下面的示例:
switch (someInt) {
case 0: ... break;
case 10: ... break;
case 102: ... break;
case 6543: ... break;
case 19303: ... break;
case 19305: ... break;
// and so forth...
}大多数编译器将使用一个未展开的分区树来找到正确的大小写,在长开关上,这会提供非常好的avg和最坏情况下的跳转来找到正确的情况。生成的伪代码如下所示:
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,取决于编译器的选择)。
发布于 2012-12-30 07:02:52
开关应该更快,只要看看字节码就够了
TABLESWITCH
1: L1
2: L2
3: L3
4: L4
5: L5
6: L6以确保这是一项特殊的行动。在现实生活中,由于JVM的优化,可能没有什么不同。但是如果我们用-Xint (interepret模式)运行您的代码,那么差别应该很明显,在我的PC上,它是63比93 (ms),赞成切换。
发布于 2012-12-30 06:49:38
这里有趣的问题是编译器如何翻译开关(可能像哈希表,或者结果可以类似于if-else结构)。它还可以根据输入进行各种优化(如果已知的话)。但是,这是编译器依赖的,我知道的任何规范中都没有定义。
所以,我不能给你答案,但我可以告诉你,如果你想改进你的测试,你可以给它输入7。这将使它通过所有的测试,直到返回一个答案,如果开关是优化的,它会给你更好的结果,如果它是一个假设-如果它会有相似的结果。只是不要硬编码7,这样编译器就不会提前知道它,使用parseint之类的方法从字符串中获取它。
https://stackoverflow.com/questions/14088824
复制相似问题