当前位置: 首页 > 编程语言 > C#

case标签的顺序对switch语句效率的影响有多大?

时间:2023-04-10 18:36:45 C#

case标签的共享顺序对switch语句的效率有多大影响?考虑:if(condition1){//Codeblock1}else{//Codeblock2}如果我知道在大多数情况下condition1为真,那么我应该将逻辑编写为:if(!condition1){//Codeblock2}else{//Codeblock1}因为我会避免跳转到第二个代码块的惩罚(注意:我的汇编语言知识有限)。这个想法是否继续使用switch语句和case标签?switch(myCaseValue){caseCase1://代码块1break;caseCase2://代码块2break;//等}如果我知道其中一种情况会更频繁地发生,我可以重新排列案例标签的顺序,以便更有效?我是不是该?在我的代码中,为了代码的可读性,我一直在按字母顺序排列case标签,但没有真正考虑过它。这是微优化吗?关于x86或x86_64等现代硬件的一些事实:您可以在AgnerFogs优秀手册中阅读有关分支预测的更多信息。switch语句通常由编译器的跳转表代替。在大多数情况下,案例的顺序根本没有任何区别。间接跳跃也有预测机制。所以问题不在于你是否更有可能进行跳跃,如果它们是可预测的,至少对于你打算运行代码的硬件而言。这根本不是一个简单的问题。但是,如果您有一个依赖于随机(或伪随机)条件的分支,您可以尝试将其重新表述为无分支语句。关于if语句的结论在我熟悉的大多数硬件上都不成立。问题不在于你在跳跃,而在于你在分支。根据比较的结果,代码可以采用两种不同的方式。这会阻塞大多数现代CPU上的管道。分支预测很常见并且在大多数情况下可以解决问题,但与您的示例无关。预测器同样可以预测比较将是错误的,因为它可能是正确的。和往常一样,请参阅维基百科:分支预测器这取决于。编译器将使用一组内部实现相关的标准来决定是将开关实现为类似if的测试序列还是跳转表。例如,这可能取决于您的案例标签集的“紧密程度”。如果您的case标签值形成一个“密集”集,编译器可能更可能使用跳转表,在这种情况下case标签的顺序无关紧要。如果它决定使用类似于if-else测试的序列,那么顺序可能很重要。但请记住,switch的主体是一个大语句,case标签为该语句提供了多个入口点。因此,编译器在该语句中重新排列case“子块”的能力(以及您的能力)可能会受到限制。为了可读性,外壳标签应该以最有效的方式排序。为效率重新排序案例标签是过早优化的案例,除非探查器明确告诉您这是一个问题。我认为即使是最初的前提——你可以通过重新排列条件来优化if语句也可能是错误的。在未优化的构建中,您可能会发现正在发生的事情的一些价值-也许吧。通常,对于任何一种情况,您都必须至少跳过一次,因此(通常)安排条件无论如何都没有好处。但这是针对非优化版本的,那么谁在乎这种优化呢?在优化构建中,我认为您可能会对编译器有时为if语句生成的内容感到惊讶。编译器可以将一个或另一个(或两个)案例移到外面的某个地方。我认为您尝试通过玩弄“先到先得”条件来天真地优化它并不一定能达到您想要的效果。最好只在检查编译器生成的内容后才执行此操作。当然,这会成为一个代价高昂的过程,因为即使对语句进行最细微的更改也会改变编译器决定生成输出代码的方式。现在,就switch语句而言,我总是使用switch来提高代码的可读性。编译器对等效于if语句的switch语句应该做的最糟糕的事情是生成相同的代码。对于许多情况,switch语句通常被编译成跳转表。然而,另一组将变量与一组值进行比较的if测试很可能会被编译器识别,从而做同样的事情。但是,我猜想使用开关可以让编译器更容易识别这种情况。如果您真的对从该条件中获得最大性能感兴趣,请考虑MSVC的ProfileGuidedOptimization(PGO或“pogo”),它使用分析运行的结果来优化条件的生成方式。我不知道GCC是否具有类似的功能。我不确定C#编译器,但我知道在汇编中,switch语句实际上可以编程为跳转到特定行,而不是像if语句那样计算表达式。因为在select中你拥有所有常量,它只是将大小写处理为行号,你直接跳转到传入的行号(大小写值)而不进行任何评估。这使得case语句的顺序根本不重要。我假设您知道只有在这是热点时才有意义。判断它是否是热点的最佳方法是运行代码、对程序计数器进行采样,并查看它是否有超过10%的时间存在。热的话看看执行if或者switch的耗时。通常它可以忽略不计,除非您的Block1和/或Block2几乎什么都不做。您可以使用探查器。我只是反复停顿。如果您不熟悉汇编语言,我建议您充分学习它以了解编译器生成的内容。这很有趣,也不难。正如其他人所说,这取决于很多事情,包括有多少案例,如何优化以及您正在运行的架构。有关有趣的概述,请参见http://ols.fedoraproject.org/GCC/Reprints-2008/sayle-reprint.pdf如果您将最常出现的情况放在第一位,这会稍微优化代码,并且由于切换器状态的工作方式相同方式。当程序进入switch并找到true条件时,它会执行它并点击break,从而退出循环。你的想法是正确的。但是,我确实认为这种优化非常小,如果它减慢了您的开发时间,那么它可能不值得。此外,如果您必须大幅修改程序流程以适应这种情况,那可能不值得。您最多只能节省几个周期,而且很可能永远看不到改进。以上就是C#学习教程:case标签的顺序对switch语句效率的影响有多大?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: