优化:switch 语句中的 case 顺序重要吗? [关闭]
Posted
技术标签:
【中文标题】优化:switch 语句中的 case 顺序重要吗? [关闭]【英文标题】:Optimization: Is the order of cases in a switch statement important? [closed] 【发布时间】:2014-06-01 20:05:38 【问题描述】:考虑使用您选择的语言(例如,Java、C、C#...)中的 switch
语句。当然,case
语句的顺序很重要,如果有失败,但假设每个case
都有一个break
,所以顺序没有语义重要性。
case
语句的顺序在考虑优化时是否重要?是按升序对案例进行排序更好,还是任何排序都没有好处?编译器可能执行的优化可能取决于case
s 的顺序。由于任何编译器可能会或可能不会选择此类优化,因此我不想在这里询问特定的语言或编译器。问题是关于可能发生的事情。
【问题讨论】:
这种语言是否适用于一组特定的编程语言? 我不会欺骗这个,但这是一个可能的欺骗:***.com/questions/2815983/… 据我所知,您提到的所有语言都没有强制要求 switch 的性能行为——所以这实际上是一个关于实现的问题,而不是语言。如果你想限制你的问题,它应该是“gcc,clang,openjdk,MS CLR”之类的。 @gexicide,我认为这是一个不错的问题,但措辞方式使其过于宽泛。如果您关心优化开关的工作方式,也许您应该关心的是编译器,而不是语言。也许改写这个问题(或重新提问,看看你在这里得到的关闭/否决票的数量)以专注于这个问题 - 例如。 “案例的顺序是否会影响开关的可能编译器优化”。编译器使用了一些重要的技巧来优化开关,因此这可能是一个非常有趣但可能不太实用的问题。 我认为这是一个合理的问题,而且不是太宽泛,因为我认为从实际的角度来看,在大多数情况下都有一个正确的答案:将最常见的情况放在首位不会有任何伤害,并且可能会有所帮助,如果 switch 语句是性能接收器。不过,它看起来确实可能是 Mystical 发现的问题的欺骗。 【参考方案1】:答案不仅取决于语言,还取决于编译器,甚至取决于您选择的编译器设置。我已经看到它在 C++ 中有所不同,具体取决于我选择的 gcc 优化设置。
这是因为编译器可能选择将 switch 语句实现为一系列测试,就像一系列 if / else if 语句一样,或者它可能选择将 switch 语句实现为跳转表。对于较早的测试,一系列测试会更快,而跳转表通常会同样快,无论顺序如何。
如果您的编译器将您的 switch 语句实现为一系列测试 - 并且不重新排序它们 - 将更有可能的情况提前放置将导致更快的代码。据我所知,将更可能的情况提前放置通常不会导致代码变慢,因此如果您的代码花费大量时间执行此 switch 语句,那么将更常见的情况提前放置也无妨。
但是,如果您没有分析过您的代码并且您不知道 switch 语句是一个性能问题,那么最好按照阅读代码的人最清楚的顺序来编写 switch 语句.
【讨论】:
另外,如果 switch case 真的非常长,以至于你开始遇到指令缓存未命中,那么即使在跳转表的情况下,把最有可能的情况放在首位也会导致加速。【参考方案2】:从这个基准来看,它确实很重要: http://pastebin.com/rJMEunAT
第一种方法在 0.2423 滴答时结束,第二种方法在 0.1654 结束
【讨论】:
【参考方案3】:对于禁止多个 case 子句匹配的语言,并且编译器至少进行了一些优化,几乎可以肯定,编写 case 子句的顺序不会有什么不同。
有三种流行的编译 switch 语句的方法:
硬编码二进制搜索
索引跳转表
散列跳转表
这三个都要求编译器重新排序子句。选择哪一个取决于语言、目标处理器、case 子句中的值分布以及可能的月相。
【讨论】:
以上是关于优化:switch 语句中的 case 顺序重要吗? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章