【问题标题】:Does jit optimize switch statements with too few branches?jit 是否会优化分支太少的 switch 语句?
【发布时间】:2012-09-13 15:35:54
【问题描述】:

最近我遇到了一个静态代码分析工具 (PMD) 抱怨 switch 语句分支太少的情况。它建议把它变成一个 if 语句,我不想​​这样做,因为我知道很快就会添加更多的案例。但我想知道javac 是否执行了这样的优化。我使用 JAD 反编译了代码,但它仍然显示一个开关。这可能是 JIT 优化的运行时吗?

更新:请不要被我的问题所误导。我不是在问 PMD,我不是在问是否需要微优化等。问题显然只是这样:当前(Oracle 1.6.x)JVM 实现是否包含一个处理开关的 JIT是否有几个分支。

【问题讨论】:

  • 我以为PMD与JIT无关?
  • 当然不是。问题不是那个..

标签: java switch-statement jit


【解决方案1】:

确定 JIT 编译器如何优化 switch 语句的方法是:

  • 阅读 JIT 编译器源代码(OpenJDK 6 和 7 是开源的),或者
  • 使用开关运行 JVM,该开关告诉它为感兴趣的类将 JIT 编译的代码转储到文件中。

请注意,与所有与性能和优化相关的问题一样,答案取决于硬件平台以及 JVM 供应商和版本。

参考:Disassemble Java JIT compiled native bytecode


如果这个问题是“纯粹的好奇”,那就这样吧。

但是,还应该指出,出于性能原因重写代码以使用 switchif 可能是一个坏主意和/或浪费时间。

  • 这可能是浪费时间,因为原始版本和手动优化版本之间的时间差异(如果有)可能微不足道。

  • 这是个坏主意,因为您的优化可能只对特定的硬件和 JVM 组合有用。对其他人来说,它可能没有效果......甚至是反优化。

简而言之,即使您知道 JIT 优化器如何处理这个问题,您也可能不应该在您的编程中考虑到它。

(当然,当您遇到真正可衡量的性能问题时例外,并且分析指出(例如)3 分支 switch 是瓶颈之一。)

【讨论】:

    【解决方案2】:

    如果你是在debug模式下编译的,反编译的时候还是能拿到switch是正常的。否则,任何调试尝试都会遗漏一些信息,例如行号和原始指令流。
    因此,您可以尝试在生产模式下编译并查看反编译结果。

    但是,switch 语句,特别是如果它预计会增长,通常被认为是代码异味,应该被评估为重构的良好候选者。

    【讨论】:

      【解决方案3】:

      至于在您澄清问题后。

      由于这对硬件和 JVM 的影响如此之大(只要遵守 JVM 规范,使用 Java 商标的 JVM 可能由 Oracle 以外的公司开发)我说唯一有效的方法是进行速度测试.

      截取一段代码,将其锁定在循环中进行大量重复,检查循环执行前后的时间。对两种解决方案重复(switch 和 if)

      这可能看起来简单而愚蠢,但它确实有效,并且比反编译、读取字节码和内存转储等要快得多。


      您必须记住,Java 实际上使用虚拟机和字节码。我很确定这一切都得到了处理和优化。我们正在使用高级语言来避免您所询问的此类微观管理和优化

      总的来说,我认为您尝试优化有点过早。如果你知道在那个开关中会有更多的案例,为什么还要麻烦呢?您是否运行了分析器?如果没有,它没有用优化。 “过早的优化是万恶之源”。您可能正在优化实际上不是瓶颈的部分代码,增加了代码的复杂性并浪费了您自己的时间来编写没有任何贡献的代码。

      我不知道您正在制作什么类型的应用程序,但经验法则说清晰是王道,您通常应该选择更简单、更优雅、自记录的解决方案。

      【讨论】:

      • 这个问题与早期/不必要的优化无关。我肯定不会那样做,只是好奇 JIT 的工作方式。
      【解决方案4】:

      javac 性能几乎没有优化。所有优化都是在运行时使用 JIT 执行的。除非您知道自己有性能问题,否则我会假设您没有。

      PMD 抱怨的是清晰度。例如

      if (a == 5) {
        // something
      } else {
        // something else
      }
      

      更清晰
      switch(a) {
         case 5:
             // something
             break;
         default:
             // something else
             break;
      }
      

      【讨论】:

      • 问题是 JIT 是否进行这种特定的优化。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-15
      • 2021-08-11
      • 2019-04-15
      • 1970-01-01
      • 2015-12-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多