对JVM的哪些更改最有利于Scala编译器和运行时?
动态语言将通过引入计划到达JVM 7的InvokeDynamic
字节代码在性能方面受益匪浅,Scala可能会受益于尾递归(不确定它是否会出现在JVM 8或更高版本中)
Scala及其现有功能集还能从JVM中获益吗?这些变化即将到来吗?
具体来说,JVM是否会对闭包和函数作为对象提高性能?
答案 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中获益。