由于编译器的优化,switch语句通常比等效的if-else-if语句(如本文中所述)要快。
这种优化实际上是如何工作的?有人有很好的解释吗?
由于编译器的优化,switch语句通常比等效的if-else-if语句(如本文中所述)要快。
这种优化实际上是如何工作的?有人有很好的解释吗?
Answers:
编译器可以在适用的情况下构建跳转表。例如,当您使用反射器查看生成的代码时,您会看到对于字符串上的大量开关,编译器实际上将生成使用哈希表调度这些代码的代码。哈希表使用字符串作为键,并将case
代码委托为值。
它比许多链式if
测试具有更好的渐近运行时间,并且即使相对较少的字符串,实际上也更快。
这是一个略微的简化,因为通常任何现代编译器遇到的if..else if ..
序列都可能被人轻易地转换为switch语句,编译器也将如此。但是只是为了增加乐趣,编译器不受语法的限制,因此可以在内部生成“ switch”之类的语句,这些语句混合了范围,单个目标等,并且它们可以(也可以)对switch和if做到这一点。 .else语句。
顺便说一句,Konrad答案的扩展是编译器可以生成一个跳转表,但这并不一定要保证(也不希望)。出于多种原因,跳转表对现代处理器上的分支预测器不利,而表本身对缓存行为不利。
switch(a) { case 0: ...; break; case 1: ...; break; }
如果编译器为此实际生成了一个跳转表,则if..else if..
由于跳转表使分支预测失败,因此替代样式代码的运行速度可能会更慢。
Switch / case语句通常可以更快地达到1层深度,但是当您开始使用2级或2级以上时,switch / case语句开始的时间是嵌套if / else语句的2-3倍。
本文有一些速度比较,突出显示了嵌套此类语句时的速度差异。
例如,根据他们的测试,示例代码如下:
if (x % 3 == 0)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else if (x % 3 == 1)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else if (x % 3 == 2)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
在等效的switch / case语句运行一半的时间内完成了:
switch (x % 3)
{
case 0:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 1:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 2:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
default:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
}
是的,这是一个基本示例,但它说明了这一点。
因此,对于仅深一层的简单类型,可能得出结论使用switch / case,但对于更复杂的比较和多个嵌套级别,则使用经典的if / else构造吗?