【问题标题】:Does a modern JVM optimize simple inline anonymous class allocation?现代 JVM 是否优化了简单的内联匿名类分配?
【发布时间】:2011-09-01 05:28:21
【问题描述】:

今天收到一个code review的意见,把这个匿名类提取到一个字段中,避免一遍又一遍地分配:

Collections.transform(new Function<Foo, Bar>(){
  Bar apply(Foo foo) {
    // do some simple local transform of foo into a Bar.
  }
});

我回答说“没关系,JVM会优化它”。虽然我知道这种“优化”不会以任何方式影响性能,而且我认为让代码可内联访问的附加价值是值得的,但我很好奇我对 JVM 优化是否正确。 所以,我的问题是 - 提议的重构绝对是无操作,因为 JVM 无论如何都会优化它,还是这里有一些微小的理论性能增益?

【问题讨论】:

    标签: java optimization jvm


    【解决方案1】:

    我不会特别期望优化它,不。

    它必须确保Collections.transform 永远不会隐藏Function,并且该方法本身永远不会使this 可见等。显然所有这些都是可行的 - 但它可能需要做很多工作在极少数情况下获得相对较小的收益。

    现在,如果不仔细检查,很难说任何特定 VM 所做的事情 - 但我认为“它不会显着影响性能”比“JVM 优化它”更合理。

    【讨论】:

    • 想了很多。有时我过于相信优化器的神奇力量。
    【解决方案2】:

    是否将其提取到字段中应该取决于您调用它的频率以及父类的持续时间。如果父类的生命周期与应用程序一样长,并且您在一个蓝月亮中调用了这个东西,为什么还要为这样一个微不足道的操作保留一个实例呢?相反,如果你经常调用这个东西,那么可以将它保存在一个变量中,以节省创建多个对象的麻烦。

    我认为我自己的经验法则是,如果内部类的范围在方法调用内,并且您的方法不是性能关键且实现很小,则将其保留在原处。

    【讨论】:

      【解决方案3】:

      我不认为 JVM 会优化它——很可能,性能损失不值得优化成本。但是,内联代码的巨大好处远远超过它。

      【讨论】:

        【解决方案4】:

        如果你想内联代码而不是每次都为函数创建一个对象,为什么不使用循环。你不会比这更有效率。但是,如果您想要可读性而不是性能(大多数情况下这是一个更好的主意),您可能会找到适合您的函数式表示法。

        List<Bar> bars = new ArrayList<Bar>();
        for(Foo foo: foos) {
           // do some simple local transform of foo into a Bar.
           bars.add(bar);
        }
        

        就个人而言,我觉得这更简单。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-03-03
          • 1970-01-01
          • 2013-08-05
          • 1970-01-01
          • 2021-10-16
          • 2017-10-18
          • 1970-01-01
          相关资源
          最近更新 更多