Scala与Java性能(HashSet和bigram生成)

Dim*_*try 12 java performance scala

我遇到了Scala和Java版本之间几乎完全相同的性能差异.我看到Java版本比Scala版本快68%.知道为什么会这样吗?

Java版本:

public class Util {
public static Set < String > toBigramsJava(String s1) {
    Set <String> nx = new HashSet <String> ();
    for (int i = 0; i < s1.length() - 1; i++) {
        char x1 = s1.charAt(i);
        char x2 = s1.charAt(i + 1);
        String tmp = "" + x1 + x2;
        nx.add(tmp);
    }
    return nx;
}
Run Code Online (Sandbox Code Playgroud)

}

Scala版本:

object Util {
def toBigramsScala(str: String): scala.collection.mutable.Set[String] = {
    val hash: scala.collection.mutable.Set[String] = scala.collection.mutable.HashSet[String]()
    for (i <-0 to str.length - 2) {
        val x1 = str.charAt(i)
        val x2 = str.charAt(i + 1)
        val tmp = "" + x1 + x2
        hash.add(tmp)
    }
    return hash
}
Run Code Online (Sandbox Code Playgroud)

}

检测结果:

scala> Util.time(for(i<-1 to 1000000) {Util.toBigramsScala("test test abc de")}) 17:00:05.034 [info] Something took: 1985ms

Util.time(for(i<-1 to 1000000) {Util.toBigramsJava("test test abc de")}) 17:01:51.597 [info] Something took: 623ms

系统:

我在Ubuntu 14.04上运行了这个,有4个内核和8Gig RAM.Java版本1.7.0_45,Scala版本2.10.2.

我的博客上有更多信息.

Eug*_*nev 10

这个scala版本的结果大致相同

object Util {
  def toBigramsScala(str: String) = {
    val hash = scala.collection.mutable.Set.empty[String]
    var i: Int = 0
    while (i <  str.length - 1) {
      val x1 = str.charAt(i)
      val x2 = str.charAt(i + 1)
      val tmp = new StringBuilder().append(x1).append(x2).toString()
      hash.add(tmp)
      i += 1
    }
    hash
  }
}
Run Code Online (Sandbox Code Playgroud)

正如我记得scala中的循环实现为在Function0上调用apply()方法,这是一种变形方法调用(从JVM/JIT的角度来看代价很高).加上javac可能会进行一些字符串连接优化.

我没有通过查找生成的字节代码来检查我的假设,但是用StringBuilder替换while和string连接使得差异可以忽略不计.

Time for Java Version: 451 millis
Time for Scala Version: 589 millis
Run Code Online (Sandbox Code Playgroud)