Switch语句中的大小写顺序是否会改变性能?

时间:2010-05-12 03:39:36

标签: c# performance micro-optimization switch-statement

假设我有一个如下所示的开关语句

switch(alphabet) {

    case "f":
        //do something
        break;

    case "c":
        //do something
        break;

    case "a":
        //do something
        break;

    case "e":
        //do something
        break;

}

现在假设我知道Alphabet e的频率最高,其次是a,c和f。所以,我只是重新构建了case语句顺序,并按如下方式进行了修改:

switch(alphabet) {

    case "e":
        //do something
        break;

    case "a":
        //do something
        break;

    case "c":
        //do something
        break;

    case "f":
        //do something
        break;
}

第二个switch语句是否会比第一个switch语句更快?如果是,如果在我的计划中,我需要多次调用此switch声明,这是否会有实质性改进?或者,如果没有,我如何使用我的频率知识来提高性能?

4 个答案:

答案 0 :(得分:21)

并不是说你应该担心。这肯定不是可以预测的东西。

对于字符串大小写标签,编译器实际上使用内部哈希表将字符串映射到跳转表中的索引。所以操作实际上是O(1) - 与标签数量无关。

对于整数标签,我相信生成的实际代码取决于标签的数量以及数字是否连续(或“几乎”连续)。如果它们是连续的(1,2,3,4 ......),那么它们将被转换成跳转表。如果有很多,那么将使用Hashtable +跳转表(与字符串一样)。如果只有少数标签,并且它们不是立即转换为跳转表的表,那么只会将转换为一系列if..then..else语句。

但是,一般情况下,您应该编写代码以便可以读取它,而不是让编译器生成“更快”的代码。

(注意我上面的描述是关于C#编译器如何在内部工作的实现细节:你不应该依赖它总是这样工作 - 事实上,它可能甚至不能完全像现在,但至少它是一般的想法。)

答案 1 :(得分:2)

对于相对较小的一组值,它们具有相同的性能。我之前尝试检查C程序的汇编代码,编译器从switch语句中的所有值中创建一个跳转表。

但如果案例值太多,那么可以肯定它们将退化为if else if,因此将您的案例“E”放在首位肯定会加快速度。

在C#中它也是applicable,C#也为一小组的switch语句生成一个跳转表,尽管只是相邻的值。所以它是O(1),即使第一个值不匹配也没有多重测试。

答案 2 :(得分:2)

这取决于编译器如何实现switch语句。

首先,你不能随意置换顺序;如果你有一个案件块 用C语言(C,C ++,C#,Java,...),而那个case块没有 在休息时终止,你不能重新安排案件,因为没有 中断意味着编译器必须实现下一个案例的落实。 如果我们忽略这种特殊情况,你可以置换其余的情况。

如果案例数量很少,编译器可能会执行案例测试 通过一系列的比较。如果案件数量适中,则可以构建 来自案例的平衡二叉树。如果病例数很多,大多数情况下 如果编译器来自,则编译器在switch值上实现索引分支 密集的。如果案例值集的一部分是密集的,而部分是 不是,编译器可以使用二叉树将案例分组 选择哪个密集集,以及密集集内的索引跳转。 (事实上​​,编译器可能在技术上做任何将控制传递给的人 适当的情况,但大多数情况下它是上述之一。)

您可以看到顺序可能很重要,也可能不重要,具体取决于编译器的方式 实现开关。对于大多数优秀的编译器而言,它并不重要。

答案 3 :(得分:-2)

我认为切换案例的方式是从上到下遍历所有案例以找到一些匹配。如果匹配,则停在那里。

因此,如果您对频率案例进行了优先排序,那么答案是肯定的,它可以在某种程度上提高性能。但我相信它没有多大帮助。