改进Scala的JVM

时间:2011-04-18 17:41:00

标签: scala jvm

对JVM的哪些更改最有利于Scala编译器和运行时?

动态语言将通过引入计划到达JVM 7的InvokeDynamic字节代码在性能方面受益匪浅,Scala可能会受益于尾递归(不确定它是否会出现在JVM 8或更高版本中)

Scala及其现有功能集还能从JVM中获益吗?这些变化即将到来吗?

具体来说,JVM是否会对闭包和函数作为对象提高性能?

4 个答案:

答案 0 :(得分:26)

基本上,John Rose一直在竞选的所有内容:)

  • Fixnums - 消除装箱/拆箱原语的费用。

  • 方法句柄 - 可以加速高阶函数并允许JVM更有效地优化它们。 SAM类型有时可能需要在单态和多态呼叫站点之间进行笨拙的翻转/翻转,以防止内联。

  • Continuations - 支持异步/并发设计,按照node.js

  • Interface Injection - 简化mixin组合和角色的实现,并且在很多情况下无需生成一些中间类并使结构类型成为可能。

  • 尾部优化 - 应该是一个明智的选择:)

通常引用Reification作为有利于Scala模式匹配的东西,但考虑到两种语言使用的不同方差方案,这在互操作方面会产生很高的成本。在这一点上,我认为物化实际上可能造成更多的伤害而不是它的好处。

我还认为期望任何会破坏Java的向后兼容性是不合理的。这不会发生。

答案 1 :(得分:13)

Scala有一些功能可以在JVM中更好地实现,例如:

  • 可在运行时访问的泛型。目前,scalac将泛型类型保存为隐藏字段(如果有问题的类是案例类)。这使得泛型在案例类中不必要地变得非常昂贵。

  • 声明网站差异。 Scala在定义站点指定类型参数的方差,而Java在调用站点处这样做。虽然这不太可能得到修复,因为它会破坏所有现有的Java通用代码。

  • 尾调用优化。 Scalac可以自己做一些尾调用优化,但只能在最简单的(自递归)情况下进行。任何其他尾调用都将像JVM一样使用堆栈空间。

  • 删除空指针。 Scala已经可以使用选项[A] 处理空引用,但由于存在于JVM上,对选项本身的引用可能为null,或者它的参数可能为null。所以你不能像Haskell那样得到非空的保证。

编辑:在列表中添加了声明 - 站点差异。

答案 2 :(得分:10)

对于元组和案例类,值类型将有助于提高性能。转义分析有助于减少这些对象的堆分配,但目前JVM无法积极地内联某些方法调用,因此无法消除这些小的不可变对象的堆分配。这导致堆垃圾并且执行时间增加3-4倍。

值类型还有助于增加数据局部性并减少内存使用量。例如,在一个简单的Array [(Int,Int)]中,每个数组条目都有一个指针+对象头的开销。使用值类型,可以完全消除此开销。

答案 3 :(得分:4)

人们经常关注InvokeDynamic - 没有意识到MethodHandles框架有很多其他优点,即使MH提供的方法引用永远不会被动态调用。

MethodHandles几乎就像是“正确反思”的高效形式。

任何大量使用反射的语言都可以从语言运行时内部使用MethodHandles中获益。