1

次のコードを実行します。

object Main {
  def main(args: Array[String]) = {
    {
      val start = System.currentTimeMillis
      println("took " + (System.currentTimeMillis - start) + " ms")
    }
    {
      val start = System.currentTimeMillis
      val took = System.currentTimeMillis - start
      println(s"took $took ms")
    }
  }
}

そしてそれは与えます:

took 246 ms
took 0 ms

しかし、2 つのブロックを交換すると、

took 0 ms
took 0 ms

なぜそうなのですか?

4

3 に答える 3

3

この方法で意味のあるものを測定できるとは信じがたいので、ピンの頭で何人の天使が踊ることができるかを推測するのと少し似ています.

コードが何にコンパイルされるかを検査するためのオプションがあります。

apm@mara:~/tmp$ skalac -Xprint:typer angeldance.scala
[[syntax trees at end of                     typer]] // angeldance.scala
package angeldance {
  object Main extends scala.AnyRef {
    def <init>(): angeldance.Main.type = {
      Main.super.<init>();
      ()
    };
    def main(args: Array[String]): Unit = {
      {
        val start: Long = java.this.lang.System.currentTimeMillis();
        scala.this.Predef.println("took ".+(java.this.lang.System.currentTimeMillis().-(start)).+(" ms"))
      };
      {
        val start: Long = java.this.lang.System.currentTimeMillis();
        val took: Long = java.this.lang.System.currentTimeMillis().-(start);
        scala.this.Predef.println(scala.StringContext.apply("took ", " ms").s(took))
      }
    }
  }
}

2 番目のケースでStringContext.sは using を使用java.lang.StringBuilderしていますが、最初のケースの式では using を使用してscala/collection/mutable/StringBuilderいます。これにより、クラスの読み込みにコストがかかる可能性があります。試してみるには、かなり興味を持っている必要があります-XX:+PrintClassLoading。として呼び出しますscala -J-XX:+PrintClassLoading

scala> val i = 5L
i: Long = 5

scala> "hello, " + i
res0: String = hello, 5

scala> :javap -
  Size 1007 bytes
  MD5 checksum bbccca3ecafe9287f07df81ea123676e
  Compiled from "<console>"
[snip]
         8: aload_0       
         9: new           #23                 // class scala/collection/mutable/StringBuilder
        12: dup           
        13: invokespecial #24                 // Method scala/collection/mutable/StringBuilder."<init>":()V
        16: ldc           #26                 // String hello, 
        18: invokevirtual #30                 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
        21: getstatic     #35                 // Field .MODULE$:L;
        24: invokevirtual #39                 // Method .i:()J
        27: invokestatic  #45                 // Method scala/runtime/BoxesRunTime.boxToLong:(J)Ljava/lang/Long;
        30: invokevirtual #30                 // Method scala/collection/mutable/StringBuilder.append:(Ljava/lang/Object;)Lscala/collection/mutable/StringBuilder;
        33: invokevirtual #48                 // Method scala/collection/mutable/StringBuilder.toString:()Ljava/lang/String;
于 2013-08-17T03:49:57.580 に答える
2

JVM のウォーミングアップ (実行時の最適化?) に関係していると思います。なぜなら、コードを低くしようとするとゼロ回になるからです (println呼び出しを 1 つ追加しました)。

object Main {
  def main(args: Array[String]) {
    println("x")
    val a = ()=> {
      val start = System.currentTimeMillis
      println("took " + (System.currentTimeMillis - start) + " ms")
    }
    val b = ()=> {
      val start = System.currentTimeMillis
      val took = System.currentTimeMillis - start
      println(s"took $took ms")
    }
    a()
    b()
  }
}
バツ
0ミリ秒かかりました
0ミリ秒かかりました
于 2013-08-16T16:43:55.663 に答える