加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

表现 – 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倍(忽略了随机时间,否则主导了这一点,是的,我加热了我的基准…).

How is the first version avoiding the performance penalty of the boxing?

编辑:这是我的分析代码:

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).

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读