我很好奇速度switch
,相信它“非常”快,但我有一个测试用例,似乎表明单个开关的速度大约与 4 一样快if
测试,当我预期(没有充分的理由)它会像 1 次测试一样快。这是我写的两个方法来比较switch
with 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()
在我的机器上这些循环需要大约在同一时间完成,这是一个惊喜。
我得出的 if 数量为“4”,因为这是给定输入范围的平均值(我认为)。
如果我减少逻辑选项的数量,if
版本明显更快。
我的问题是:
是那个吗switch
实际上isn't这么快,还是这在某种程度上是一个“不公平”的测试?
这在某种程度上是一种不公平的比较。大部分 CPU 时间将用于处理模运算:i % 7
。即使在最新最好的 CPU 上,模数也非常慢,并且执行时间可能比您尝试进行基准测试的 if() 或 switch() 实现长 20 倍。
此外,有两种不同的方法可以优化 switch 语句。一种是通过查找表,它用于顺序情况,例如您提出的情况。另一种方法是使用搜索分区树, 在适当情况下。当案件发生时会发生这种情况sparse,例如以下示例:
switch (someInt) {
case 0: ... break;
case 10: ... break;
case 102: ... break;
case 6543: ... break;
case 19303: ... break;
case 19305: ... break;
// and so forth...
}
大多数编译器将使用展开的分区树来查找正确的情况,这在长开关上提供了非常好的平均和最坏情况跳转,以达到正确的情况。由此产生的伪代码将是这样的:
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 个),而分区树版本将接近 sqrt(n)(最差 8-9 个条件,平均 5-7 个,具体取决于编译器选择)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)