微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

数组构造函数优化-Double的装箱

如何解决数组构造函数优化-Double的装箱

在对应用程序进行性能分析时,可以看到在Array[Double]构造函数中完成的Double值的装箱,如下所示(从JMC / JFR复制):

Double Double.valueOf(double)   1472
   Double BoxesRunTime.BoxTodouble(double)  1472
      Object WrappedArray$ofDouble.apply(int)   1468
         Object IndexedSeqLike$Elements.next()  1365
            void Iterator.foreach(Function1)    1365
               void Iterator.foreach$(Iterator,Function1)  1365
                  void AbstractIterator.foreach(Function1)  1365
                     Object Array$.apply(Seq,classtag) 1365

当我检查Array构造函数代码时,有以下注释(请参阅Array.scala#L182-L192):

  // Subject to a compiler optimization in Cleanup.
  // Array(e0,...,en) is translated to { val a = new Array(3); a(i) = ei; a }

这种翻译听起来很合理。为什么我在调用栈中仍然看到Iterator / BoxTodouble?注释是否过时,或者我需要一些特定的编译器设置才能应用此优化?

调用数组构造函数代码一个类成员初始化:

  var elements = Array[Double](
    1,1,1
  )

我已经使用Scala 2.12.12和2.13.3对此进行了测试

注释是在提交Optimize primitive Array(e1,en)添加的(在Scala 2.11.0-M1中)。

解决方法

优化似乎很脆弱。更改涉及的类型和文字会导致(或不会)完成优化。

var el = Array[Double](1)

var el = Array[Double](1.0)

两者都产生难看的代码:

       0: aload_0
       1: invokespecial #27                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: getstatic     #33                 // Field scala/Array$.MODULE$:Lscala/Array$;
       8: getstatic     #38                 // Field scala/runtime/ScalaRunTime$.MODULE$:Lscala/runtime/ScalaRunTime$;
      11: iconst_1
      12: newarray       double
      14: dup
      15: iconst_0
      16: dconst_1
      17: dastore
      18: invokevirtual #42                 // Method scala/runtime/ScalaRunTime$.wrapDoubleArray:([D)Lscala/collection/immutable/ArraySeq;
      21: getstatic     #47                 // Field scala/reflect/ClassTag$.MODULE$:Lscala/reflect/ClassTag$;
      24: invokevirtual #51                 // Method scala/reflect/ClassTag$.Double:()Lscala/reflect/ManifestFactory$DoubleManifest;
      27: invokevirtual #55                 // Method scala/Array$.apply:(Lscala/collection/immutable/Seq;Lscala/reflect/ClassTag;)Ljava/lang/Object;
      30: checkcast     #56                 // class "[D"
      33: putfield      #18                 // Field el:[D
      36: return
}

var el = Array(1.0)

var el: Array[Double] = Array(1)

产生了漂亮的结果:

       0: aload_0
       1: invokespecial #22                 // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iconst_1
       6: newarray       double
       8: dup
       9: iconst_0
      10: dconst_1
      11: dastore
      12: putfield      #13                 // Field el:[D
      15: return

我也尝试过Dotty,并且似乎将优化应用于所有变体。

发布为scala/bug#12201

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。