Vector.min
является implemented вКаким образом Scala может избежать штрафа за бокс и распаковку?
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 раз медленнее (без учета времени в случайном, которые в противном случае доминирует над этим, и да, я нагретым моими тестами до ...).
Как первая версия избегает штрафа за производительность бокса?
Edit: вот мой профилирующий код:
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
не приводит к боксу.
Извините, у меня нет времени проверять себя прямо сейчас, но, видимо, вы используете 'сокращение' в своей собственной реализации вместо' reduceLeft'. Может ли это объяснить замедление? – paradigmatic
«нет бокса или распаковки» - как вы пришли к такому выводу (как я этому не верю) –
@paradigmatic, oops, fixed, не влияет на то, что я вижу. –