我目前正在使用switch语句来处理传入消息的类型,这些消息有20种左右不同的情况。其中一些情况比其他情况更容易发生。
热点编译器是否能够优化检查案例的顺序以找到要执行的正确案例,还是应该对我的代码进行结构化,以便最常见的案例首先出现:
switch(messageType)
{
case MOST_COMMON:
// handle it
break;
...
case LEAST_COMMON:
// handle it
break;
}
所有情况都是互斥的。
使用策略模式和在消息类型上进行Map查找会更好吗?
性能是关键问题,因为我每秒要处理数千条消息,并试图减少对象创建和方法调用的开销。
非常感谢,
克里斯
编辑:
感谢您的指导。
messageType是一个整数,其值的范围很窄,因此看起来它将编译为" tableswitch"字节码,因此无需对大小写进行重新排序。
JVM规范的相关部分位于http://java.sun.com/docs/books/jvms/second_edition/html/Compiling.doc.html#14942
IIRC大多数编译器使用查找表处理C和C ++中的switch语句。 Java可能做同样的事情。 但是我可能是错的。
Java的可能重复项:If vs. Switch
JIT应该在执行期间优化路径。 对两种机制的ID进行简要介绍,以确保
@ AndyThomas-Cramer除了这是switch-vs-map。
@Dave Newton-我正在看两个问题的内容。 这个问题的前提是假定开关好像/其他链一样实现。 前面的问题说明了它们是如何实际实现的。
开关盒顺序是否可能影响速度?
除非您确定此switch语句会导致性能问题,否则我建议您过早进行优化。另外,请查看该问题的可接受答案。
嗨,迈克,点很重要:)该代码每个工作日处理几亿个事件,约占该程序CPU周期的30%。 在深入探讨JVM规范之前,只想对JIT发表意见。
如果案例是enum值或密集分布的int值,那么一旦JIT编译器启动将所有内容转换为查找表,按顺序处理便无济于事。
如果您使用的是Java7字符串开关或稀疏分布的值,那么最常见的应该放在第一位,因为它变成了一组类似if的级联测试和分支操作。
使用java7字符串开关,它会变慢,因为它会变成级联,如果类似的语句在对字符串进行评估时将使用equals
嗨,迈克,switch是在一个整数范围内的值,因此我认为答案是查询表,不需要对子句重新排序。
@马克,我想我同意。 您是要指出我的答案的一部分是错误的,还是只是对字符串开关进行了一般性的评论?
它只是一句话:)
switch语句是执行查找以确定要跳转到哪个代码块的查找。它不是一系列的if / else检查,并且声明块的顺序对性能没有影响。即它们都是大小写相等且立即检查的情况。
与伪代码相同(对于较小的int值范围)
goto case_label[messageType.ordinal()];
对于较大的int值范围,将使用其他表结构。 (我假设它是一个哈希表)
CPU可以使用分支预测,并且如果一种情况比其他情况更常见,则可以动态优化执行。