Sco*_*son 10 performance boxing scala
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)
}
Run Code Online (Sandbox Code Playgroud)
当你描述
Vector.fill(1000000)(scala.util.Random.nextLong).min
Run Code Online (Sandbox Code Playgroud)
它很快,没有拳击或拆箱.但是,如果你写的是明显相同的
val cmp = implicitly[Ordering[Long]]
Vector.fill(1000000)(scala.util.Random.nextLong).reduceLeft((x, y) => if (cmp.lteq(x, y)) x else y)
Run Code Online (Sandbox Code Playgroud)
它的运行速度大约慢了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))
}
Run Code Online (Sandbox Code Playgroud)
我看到使用min
大约20ms的时间,使用reduceLeft
~200ms.我用这个代码描述了这个代码YourKit
; 这是调用树的屏幕抓取,显示min
不会导致任何装箱.
我觉得第一个版本推断java.lang.Long
的B
.因此仍然存在拳击,但仅在填充向量时,之后所有比较都在盒装对象之间.
在第二个版本中,由于类型为cmp
as Ordering[Long]
,java.lang.Long
因此向量中的s必须在传递给之前取消装箱cmp.lteq(x, y)
.
归档时间: |
|
查看次数: |
424 次 |
最近记录: |