表现 – Scala的.min如何避免拳击和开箱的惩罚?
发布时间:2020-12-16 19:09:28 所属栏目:安全 来源:网络整理
导读:Vector.min是 implemented as 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.
Vector.min是
implemented as
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)) 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)) x else y))._1 } while(true) { println((minTiming,reduceLeftTiming)) } 我看到时间使用最小约20ms,使用?200ms的reduceLeft.我使用YourKit对这段代码进行了分析;这是一个screen grab的呼叫树,显示min不会导致任何拳击. 解决方法
我认为第一个版本推测为B.对于java.lang.Long.所以仍然有拳击进行,但只有填补向量,然后所有的比较是在盒装的对象之间.
在第二个版本中,由于cmp的类型为Ordering [Long],所以向量中的java.lang.Longs必须先被取消装箱,然后再传递给cmp.lteq(x,y). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |