【发布时间】:2012-05-24 06:48:04
【问题描述】:
Vector.min 是implemented
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 倍(忽略 Random 中的时间,否则它会占主导地位,是的,我预热了我的基准测试......)。
第一个版本如何避免拳击的性能损失?
编辑:这是我的分析代码:
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 毫秒,使用 reduceLeft 的时间约为 200 毫秒。我已经使用YourKit 分析了这段代码;这是调用树的screen grab,显示min 不会导致任何装箱。
【问题讨论】:
-
抱歉,我现在没有时间检查自己,但显然,您在自己的实现中使用
reduce而不是reduceLeft。是否可以解释放缓? -
“没有装箱或拆箱” - 你是怎么得出这个结论的(我不相信)
-
@paradigmatic,哎呀,已修复,不会影响我看到的内容。
-
如果您改用
val cmp = implicitly[Ordering[java.util.Long]]会怎样?这会影响时间吗? -
@oxbow_lakes,我已经包含了我的分析代码,以及来自 YourKit 的屏幕截图,显示
reduceLeft拳击,min没有。
标签: performance scala boxing