10

Vector.minとして実装されます

def min[B >: A](implicit cmp: Ordering[B]): A = {
  if (isEmpty)
    throw new UnsupportedOperationException("empty.min")
  reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y)
}

プロフィールを作成するとき

Vector.fill(1000000)(scala.util.Random.nextLong).min

それは高速で、ボクシングやアンボクシングは行われていません。ただし、明らかに同等のものを書く場合

val cmp = implicitly[Ordering[Long]]
Vector.fill(1000000)(scala.util.Random.nextLong).reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y)

実行速度は約10倍遅くなります(ランダムでの時間を無視すると、それ以外の場合はこれを支配します。そうです、ベンチマークをウォームアップしました...)。

最初のバージョンはボクシングのパフォーマンスの低下をどのように回避していますか?

編集:これが私のプロファイリングコードです:

val cmp = implicitly[Ordering[Long]]

def randomLongs = Vector.fill(1000000)(scala.util.Random.nextLong)

def timing[R](f: => R): (Long, R) = {
  val startTime = System.nanoTime
  val result = f
  ((System.nanoTime - startTime) / 1000000, result)
}

def minTiming = { val r = randomLongs; timing(r.min)._1 }
def reduceLeftTiming = { val r = randomLongs; timing(r.reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y))._1 }

while(true) {
  println((minTiming, reduceLeftTiming))
}

min約20ミリ秒、約200ミリ秒の時間を使用していreduceLeftます。YourKit;を使用してこのコードのプロファイルを作成しました。これは、ボクシングが発生しないことを示すコールツリーのスクリーングラブです。min

4

1 に答える 1

5

私は最初のバージョンがを推測java.lang.Longすると思いますB。したがって、ボックス化はまだ進行中ですが、ベクトルを埋めている間のみであり、その後、すべての比較はボックス化されたオブジェクト間で行われます。

2番目のバージョンでは、のタイプがcmpとして指定されているため、ベクトル内のsはOrdering[Long]java.lang.Longに渡される前にボックス化されていない必要がありますcmp.lteq(x, y)

于 2012-05-24T08:34:31.807 に答える