【问题标题】:Representation and efficiency of Switch statements in bytecode?字节码中 Switch 语句的表示和效率?
【发布时间】:2012-02-03 15:37:57
【问题描述】:

虽然 switch 语句可以表示为一系列 if 语句,但似乎在将 Java switch 语句编译为字节码时,使用了不同的方法。

  • 字节码使用什么表示?
  • 我假设这种替代表示是出于效率原因,那么与仅使用 if 语句表示的效率相比如何?
  • 是否有任何其他因素导致使用此表示?

【问题讨论】:

  • 这个link 很好地涵盖了它。

标签: java performance switch-statement bytecode representation


【解决方案1】:

考虑这个简单的 JavaScript 示例

var SwitchCases = [
// case 1
 function() { return "one"; },
// case 2
 function() { return "two"; },
// case 3
 function() { return "three"; },
// default
 function() { return ""; }
];
var SwitchCaseMin = 1;
var SwitchCaseMax = 3;
var SwitchCaseDefault = true;

function FakeSwitchCase(switch) {
 if(switch > SwitchCaseMax || switch < SwitchCaseMin) {
  if(SwitchCaseDefault == true) {
   return SwitchCases[SwitchCases.length-1]();
  }
 } else {
  return SwitchCases[switch - SwitchCaseMin]();
 }
}

关键部分是

SwitchCases[switch - SwitchCaseMin]();

想象一下,如果有很多案例,评估它们的代码不会变得更大,但如果我们使用 IF..ELSE IF...ELSE,执行时间会随着每个添加案例而增加。

在真正的 switch case 实现中,SwitchCases(来自上面的代码)将是一个数组/查找表,其中包含到 Case 代码块出现的函数位置的标签(读取:偏移)。

编辑

在java中,上面的switch case会被编译成下面的字节码

[tableswitch 0xAA]
[padding bytes 0x00 or 0x0000 or 0x000000]
[offset of SwitchCases[3]] // default case
[SwitchCaseMin] // 1
[SwitchCaseMax] // 3
[offset of SwitchCases[0]] // case 1
[offset of SwitchCases[1]] // case 2
[offset of SwitchCases[2]] // case 3

【讨论】:

  • 我的问题是关于Java 和相应的bytecode,所以我认为Javascript 的例子并不合适。
  • @Treebranch - 我有点模棱两可,但上面的代码与 Java 字节码的工作方式不谋而合,我将进行更新以详细说明。
【解决方案2】:

阅读spec。在 Java 中,如果您编写一个 switch 语句,那么根据各种情况,switch 将转换为字节码中的 tableswitch 指令。本质上是一个跳表。不过,如果 JIT 可以将字节码优化为更有效的东西,那么字节码的外观可能无关紧要。当然,这取决于平台。

【讨论】:

  • 我试图理解的部分内容是,是什么让这个带有(跳转表)的表比也跳转到特定点的字节码 if 语句更有效。
  • 那么您不是在问 Java 特定的性能问题 - 这是您可以轻松地在谷歌上搜索“jump table vs if”的问题。这里有一些东西可以帮助您入门:dotnetperls.com/if-switch-performance
  • 这是一个有趣的链接,但我对 JVM 特别感兴趣。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-14
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-02
相关资源
最近更新 更多