C# 如果与切换速度

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/445067/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:38:13  来源:igfitidea点击:

If vs. Switch Speed

c#performanceswitch-statementif-statement

提问by Dirk Vollmar

Switch statements are typically faster than equivalent if-else-if statements (as e.g. descibed in this article) due to compiler optimizations.

由于编译器优化,switch 语句通常比等效的 if-else-if 语句(如本文所述)更快。

How does this optimization actually work? Does anyone have a good explanation?

这种优化实际上是如何工作的?有没有人有好的解释?

采纳答案by Konrad Rudolph

The compiler can build jump tables where applicable. For example, when you use the reflector to look at the code produced, you will see that for huge switches on strings, the compiler will actually generate code that uses a hash table to dispatch these. The hash table uses the strings as keys and delegates to the casecodes as values.

编译器可以在适用的情况下构建跳转表。例如,当您使用反射器查看生成的代码时,您会发现对于字符串上的巨大开关,编译器实际上会生成使用哈希表来分派这些代码的代码。哈希表使用字符串作为键并将case代码作为值委托给代码。

This has asymptotic better runtime than lots of chained iftests and is actually faster even for relatively few strings.

与许多链式if测试相比,这具有渐近更好的运行时间,并且实际上即使对于相对较少的字符串也更快。

回答by Calyth

The no-match stats may not be good.

不匹配的统计数据可能不好。

If you actually download the source, the no match values are known to be 21, in both the if and switch case. A compiler should be able to abstract away, knowing which statement should be run at all times, and a CPU should be able to branch predict properly.

如果您实际下载源代码,则在 if 和 switch 情况下,已知不匹配值都是 21。编译器应该能够抽象出来,知道应该始终运行哪个语句,并且 CPU 应该能够正确地进行分支预测。

The more interesting case is when not every case breaks, in my opinion, but that may not have been the scope of the experiment.

更有趣的情况是,在我看来,并非每个案例都破裂,但这可能不是实验的范围。

回答by olliej

This is a slight simplification as typically any modern compiler that encounters a if..else if ..sequence that could trivially be converted into a switch statement by a person, the compiler will as well. But just to add extra fun the compiler is not restricted by syntax so can generate "switch" like statements internally that have a mix of ranges, single targets, etc -- and they can (and do) do this for both switch and if..else statements.

这是一个轻微的简化,因为通常任何现代编译器遇到一个if..else if ..序列,该序列可以被一个人轻松转换为 switch 语句,编译器也会这样做。但只是为了增加额外的乐趣,编译器不受语法限制,因此可以在内部生成“switch”之类的语句,这些语句具有范围、单个目标等的混合 - 他们可以(并且确实)为 switch 和 if 执行此操作。 .else 语句。

Anyhoo, an extension to Konrad's answer is that the compiler may generate a jump table, but that's not necessarily guaranteed (nor desirable). For a variety of reasons jump tables do bad things to the branch predictors on modern processors, and the tables themselves do bad things to cache behaviour, eg.

Anyhoo,康拉德答案的扩展是编译器可能会生成一个跳转表,但这不一定保证(也不可取)。由于各种原因,跳转表对现代处理器上的分支预测器做坏事,而表本身对缓存行为做坏事,例如。

switch(a) { case 0: ...; break; case 1: ...; break; }

If a compiler actually generated a jump table for this it would likely be slower that the alternative if..else if..style code because of the jump table defeating branch prediction.

如果编译器实际上为此生成了一个跳转表,则可能会比替代if..else if..样式代码更慢,因为跳转表失败了分支预测。

回答by olliej

Switch/case statements may be typically faster 1-level deep, but when you start getting into 2 or more, switch/case statements start taking 2-3 times as long as nested if/else statements.

switch/case 语句通常在 1 级深度时更快,但是当你开始进入 2 个或更多时,switch/case 语句开始花费嵌套 if/else 语句的 2-3 倍。

This article has some speed comparisonshighlighting the speed differences when such statements are nested.

这篇文章有一些速度比较,突出了嵌套这些语句时的速度差异。

For example, according to their tests, sample code like the following:

例如,根据他们的测试,示例代码如下:

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;

finished in halfthe time the equivalent switch/case statement took to run:

运行等效的 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;
    }

Yeah it's a rudimentary example, but it illustrates the point.

是的,这是一个基本的例子,但它说明了这一点。

So a conclusion might be use switch/case for simple types that are only one level deep, but for more complex comparisons and multiple nested levels use the classic if/else constructs?

所以结论可能是对只有一层深的简单类型使用 switch/case,但是对于更复杂的比较和多个嵌套级别,使用经典的 if/else 构造?

回答by Ralph

The only advantage of the if over case is when there is a noticeable increase of occurrence frequency of the first case.

if over case 的唯一优势是当第一种情况的发生频率明显增加时。

Not sure exactly where the threshold is, but I use case syntax unless the first "almost always" passes the first test.

不确定阈值的确切位置,但我使用 case 语法,除非第一个“几乎总是”通过第一个测试。