对于Scala编译器和运行时,哪些JVM的改变会带来最大的好处呢?
引入JVM 7中预定的InvokeDynamic
字节码将极大地提高动态语言的性能,而尾递归可能会使Scala受益(不确定它是否会出现在JVM 8或之后版本)。
除此之外,有哪些其他的JVM更改可以让Scala在其当前特性集的基础上受益呢?这些更改是否已经在规划之中?
具体而言,有没有JVM的更改可以提高闭包和函数作为对象的性能?
基本上,一切都是John Rose一直在倡导的 :)
Fixnums - 用于消除装箱/拆箱原语的成本。
Method Handles - 可以加速高阶函数并使JVM更有效地进行优化。SAM类型有时需要在单态和多态调用站点之间翻转,这可能会导致内联失败。
Continuations - 用于支持异步/并发设计,如node.js
接口注入 - 简化混合组合和角色实现,以及消除生成某些中间类的需要,并在许多情况下使结构类型不需要反射变为可能。
尾调用优化 - 应该是很容易处理的 :)
重新实例化经常被引用为有益于Scala模式匹配的东西,但在互操作性方面代价很高,考虑到两种语言使用的不同变异方案。此时,我认为重新实例化可能实际上会造成更多伤害而不是好处。
我还认为期望任何会破坏Java向后兼容性的事情是不合理的。这只是不会发生的。
Scala有一些功能更适合在JVM中实现,例如:
泛型在运行时可访问。目前,scalac将泛型类型保存为隐藏字段(如果所涉及的类是case class)。虽然这使得case类中的泛型变得不必要地昂贵。
声明点变异。Scala指定了类型参数的变异点位置,而Java则在调用点指定。但这很不可能得到修复,因为它会破坏所有现有的Java泛型代码。
尾部调用优化。Scalac可以自行进行一些尾部调用优化,但仅限于最简单的(自身递归)情况。任何其他尾调用都将像在JVM中使用堆栈空间。
消除空指针。Scala已经可以使用Option[A]处理null引用,但由于位于JVM上,选项本身的引用可能为空,或者其参数可能为空。因此,您不能像Haskell那样保证非null性。
编辑:将声明点变异添加到列表中。
值类型对于元组和 case 类来说,在性能方面会有很大的帮助。逃逸分析可以在一定程度上减少这些对象的堆分配,但是目前 JVM 无法足够积极地内联某些方法调用,因此无法消除这些小的不可变对象的堆分配。这导致了堆垃圾和3-4倍的执行时间。
值类型还可以增加数据局部性并减少内存使用。例如,在一个简单的Array[(Int, Int)] 中,每个数组条目都将有一个指针 + 对象头的开销。使用值类型可以完全消除这种开销。
人们通常关注InvokeDynamic-却没有意识到MethodHandles框架有很多其他优点,即使MH提供的方法引用从未被动态调用。
MethodHandles几乎就像是一种高性能的“正确执行的反射”形式。
任何大量使用反射的语言都可能从在语言运行时内部使用MethodHandles中获得好处。