我是一名非常熟练的C#开发人员,但需要开始编写适用于JVM的代码。与C#相比,Java语言功能较差,因此我对Scala提供的功能感兴趣。
然而,当在Scala中听到所有运算符只是方法时,我开始怀疑对数学繁重计算会产生的性能影响(这对我的团队编写的应用程序类型很重要)
所以我运行了一些简单的基于int的测试,发现Scala比同等的Java代码慢大约30倍。不好!谁能告诉我我做错了什么?或者如何提高scala示例的计算性能以与Java相提并论?
UPDATE1:正如前两个答案所指出的,我是一个超级菜鸟并在IntelliJ IDE中运行它。我不知道如何通过java命令行运行scala应用程序,这可能是IntelliJ问题。感谢帮助人员,在继续执行perf测试之前,我需要调查scala的简单命令行执行,因为IDE给出的结果显然太不准确了。
UPDATE2:Luigi在评论中说他在IntelliJ中获得了相同的时间,所以看起来我的差异不是因为IntelliJ?关于这可能是什么的任何其他想法?我将尝试通过命令行运行并使用我的结果发布更新。
UPDATE3: 通过命令行运行后,我得到相同的30倍性能差异 我的电脑是3核AMD x64 3.4Ghz,运行J2SE 6 jdk 64bit 1.6.0_31,Window7。
这是我的运行时: Java:210ms Scala:在2000到7400ms之间(通常是7000范围)
所以,我想问题仍然存在。为什么scala在我的平台上运行得如此之慢?使用java 64bit运行时,还是使用Java 6?
运行时版本:
C:\Users\jason>java -showversion
java version "1.6.0_31"
Java(TM) SE Runtime Environment (build 1.6.0_31-b05)
Java HotSpot(TM) 64-Bit Server VM (build 20.6-b01, mixed mode)
C:\Users\jason>scala
Welcome to Scala version 2.9.1-1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_31).
更新4,而我的原始测试有30倍的差异,将迭代次数增加到100000000导致差异缩小到大约33%,所以看起来scala仍然被我的机器上的一些未知的初始化成本所支配。我会以最高评级的答案结束这个,因为我认为我们不会发现性能问题,因为除了我看到这个问题之外没有人:(
以下是我的示例应用:
//scala
object HelloWorld {
//extends Application {
def main(args: Array[String]) {
println("hello scala")
var total: Long = 0
var i: Long = 0
var x: Long=0;
//warm up of the JVM to avoid timing of runtime initialization
while (i < 100000)
{
x=i;
x += x - 1;
x -= x + 1;
x += 1;
x -= 1;
total += x;
i+=1;
}
//reset variables
total = 0
i = 0;
//start timing
var start: Long = System.nanoTime
//run test
while (i < 100000) {
x=i;
x += x - 1;
x -= x + 1;
x += 1;
x -= 1;
total += x;
i+=1;
}
var end: Long = System.nanoTime
System.out.println("ms, checksum = ")
System.out.println((end - start) / 1000)
System.out.println(total)
}
}
这里是java等价物,快30倍
//java
public class app {
public static void main(String[] args)
{
String message = "hello, java";
System.out.println(message);
long total = 0;
//warm up of the JVM to avoid timing of runtime initialization
for(long i=0;i< 100000;i++)
{
long x=i;
x+=x-1;
x-=x+1;
x++;
x--;
total+=x;
}
//reset variables
total = 0;
//start timing and run test
long start = System.nanoTime();
for(long i=0;i< 100000;i++)
{
long x=i;
x+=x-1;
x-=x+1;
x++;
x--;
total+=x;
}
long end = System.nanoTime();
System.out.println("ms, checksum = ");
System.out.println((end-start)/1000);
System.out.println(total);
}
}
答案 0 :(得分:17)
所以,我想我自己想出了答案。
问题在于对System.nanoTime
的调用。这样做有一些初始化成本(加载Java基础库等),从Java运行时调用加载比从Scala运行时加载要便宜得多。
我通过更改total的初始值来证明这一点,而不是将其设置为
var total: Long = System.nanoTime()
这是在第一个“预热”循环之前添加的,现在这样做会使应用程序的两个版本(Java和Scala)同时运行:大约2100次1000000次迭代。
感谢你们这些人的帮助,如果没有你们的帮助,我不会想到这一点。
ps:我会按原样留下“已接受的答案”,因为如果没有他的帮助我就不会跟踪这个问题。答案 1 :(得分:10)
我重新运行了你的代码(并且增加了周期数x1000,所以要在基准测试中获得一些意义)。
结果:
Scala: 92 ms
Java: 59 ms
您可以看到Java的速度提高了30%。
查看字节码,我可以说两个版本几乎完全相同 - 所以区别很奇怪(字节码列表很长,所以我不会在这里发布)。
增加计数x10000得出:
Scala: 884 ms
Java: 588 ms
由于结果相当稳定,因此某些地方应该存在一些不变因素。也许在某些参数中&#34; scala&#34;跑者转到JVM?
编辑:
我的配置:
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) 64-Bit Server VM (build 20.1-b02, mixed mode)
$ scala -version
Scala code runner version 2.9.0.1 -- Copyright 2002-2011, LAMP/EPFL
$ inxi -SCD
System: Host the-big-maker Kernel 2.6.35-22-generic x86_64 (64 bit) Distro Linux Mint 10 Julia
CPU: Quad core AMD Phenom II X4 965 (-MCP-) cache 2048 KB flags (lm nx sse sse2 sse3 sse4a svm)
Clock Speeds: (1) 800.00 MHz (2) 800.00 MHz (3) 800.00 MHz (4) 800.00 MHz
Disks: HDD Total Size: 750.2GB (5.8% used) 1: /dev/sda OCZ 90.0GB
2: /dev/sdb ST3500413AS 500.1GB 3: /dev/sdc ST3802110A 80.0GB
4: /dev/sdd Maxtor_6Y080M0 80.0GB
答案 2 :(得分:8)
$ javac app.java
$ scalac app.scala
$ scala HelloWorld
hello scala
ms, checksum =
1051
-100000
$ java app
hello, java
ms, checksum =
1044
-100000
我做错了什么?