【发布时间】:2014-04-30 03:25:39
【问题描述】:
我遇到了这个old question,并用 scala 2.10.3 做了以下实验。
我重写了 Scala 版本以使用显式尾递归:
import scala.annotation.tailrec
object ScalaMain {
private val t = 20
private def run() {
var i = 10
while(!isEvenlyDivisible(2, i, t))
i += 2
println(i)
}
@tailrec private def isEvenlyDivisible(i: Int, a: Int, b: Int): Boolean = {
if (i > b) true
else (a % i == 0) && isEvenlyDivisible(i+1, a, b)
}
def main(args: Array[String]) {
val t1 = System.currentTimeMillis()
var i = 0
while (i < 20) {
run()
i += 1
}
val t2 = System.currentTimeMillis()
println("time: " + (t2 - t1))
}
}
并将其与以下 Java 版本进行比较。为了与 Scala 进行公平比较,我有意识地将函数设为非静态函数:
public class JavaMain {
private final int t = 20;
private void run() {
int i = 10;
while (!isEvenlyDivisible(2, i, t))
i += 2;
System.out.println(i);
}
private boolean isEvenlyDivisible(int i, int a, int b) {
if (i > b) return true;
else return (a % i == 0) && isEvenlyDivisible(i+1, a, b);
}
public static void main(String[] args) {
JavaMain o = new JavaMain();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 20; ++i)
o.run();
long t2 = System.currentTimeMillis();
System.out.println("time: " + (t2 - t1));
}
}
这是我电脑上的结果:
> java JavaMain
....
time: 9651
> scala ScalaMain
....
time: 20592
这是(Java HotSpot(TM) 64 位服务器 VM,Java 1.7.0_51)上的 scala 2.10.3。
我的问题是 scala 版本的隐藏成本是多少?
非常感谢。
【问题讨论】:
-
你能把它改成和scala里的代码完全一样吗?例如,if-else 语句可能不会被视为与
isEvenlyDivisible中的三元运算符完全相等。速度比较无关紧要,但现在的代码并不完全相等。另外,是否先预热 JVM,然后再提供 X 次运行的平均值? -
预热 JVM 很重要。反编译字节码也可能会产生一些见解。
-
已编辑。我运行每个基准测试 20 次,并在 Scala 中使用
while来避免创建闭包。根据经验,Scala 每次输出之间的时间间隔也更长。 -
考虑到您正在测试解释器而不是 JITed 性能.. scala 代码运行速度可能会变慢并不令人意外 - 一些额外的间接。现在,如果我们正在测试实际的 JITed 代码?不太确定会有什么不同。
-
@Voo:进行 JITed 的正确方法是什么?我编译了这两个文件并运行了生成的
.class文件。无论如何,请参阅我的答案以获得更新的结果。
标签: java performance scala jvm microbenchmark