如何优化Scala中的理解和循环?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (78)

所以Scala应该和Java一样快。

下面是我的Java解决方案,在我的机器上完成需要0.7秒:

public class P005_evenly_divisible implements Runnable{
    final int t = 20;

    public void run() {
        int i = 10;
        while(!isEvenlyDivisible(i, t)){
            i += 2;
        }
        System.out.println(i);
    }

    boolean isEvenlyDivisible(int a, int b){
        for (int i = 2; i <= b; i++) {
            if (a % i != 0) 
                return false;
        }
        return true;
    }

    public static void main(String[] args) {
        new P005_evenly_divisible().run();
    }
}

这里是我的“直接翻译”到Scala,它需要103秒

object P005_JavaStyle {
    val t:Int = 20;
    def run {
        var i = 10
        while(!isEvenlyDivisible(i,t))
            i += 2
        println(i)
    }
    def isEvenlyDivisible(a:Int, b:Int):Boolean = {
        for (i <- 2 to b)
            if (a % i != 0)
                return false
        return true
    }
    def main(args : Array[String]) {
        run
    }
}

最后,这里是我尝试的函数式编程,它需要39秒

object P005 extends App{
    def isDivis(x:Int) = (1 to 20) forall {x % _ == 0}
    def find(n:Int):Int = if (isDivis(n)) n else find (n+2)
    println (find (2))
}

在Windows 7 64位上使用Scala 2.9.0.1。如何提高性能?我做错什么了吗?还是Java速度快得多?

提问于
用户回答回答于

这种情况下的问题是,从for-表达式内部返回。这反过来会被转换成一个非LocalReturException的抛出,这个抛出会在封闭方法中捕捉到。优化器可以消除前程,但还不能消除抛出/捕获。扔/接是昂贵的。但是,由于这种嵌套返回在Scala程序中很少见,优化器还没有解决这种情况。目前正在改进优化器,希望能很快解决这个问题。

用户回答回答于

问题很可能是使用for方法理解isEvenlyDivisible.替代for等量while循环应该消除Java的性能差异。

与Java相反for斯卡拉循环for理解实际上是高级方法的语法糖;在本例中,将foreach方法的Range对象。斯卡拉氏for是非常普遍的,但有时会导致痛苦的表现。

可能想尝试一下-optimize在Scala版本2.9中标记。观察到的性能可能取决于使用中的特定JVM,JIT优化器有足够的“热身”时间来识别和优化热点。

扫码关注云+社区