Scala: выполнение преобразований Array изменяется при наличии другого блока Array - PullRequest
0 голосов
/ 19 января 2019

При тестировании типов коллекций Scala я наткнулся на аномалию.

Когда Array[Int] объявлен в том же классе, что и Array[BoxedInt], производительность существенно меняется. На простых map он работает быстрее, но в других тестовых случаях медленнее.

Я сравнил 2.11.8 и 2.12.8 (параметры по умолчанию), используя sbt-jmh (10 прогревов, 20 прогонов), и это происходит в обоих случаях. Когда штучный массив достаточно мал, эффект исчезает. Я попробовал это на List, но не наблюдал того же эффекта.

Что происходит?

// 2.11.8 (without boxed array)
[info] Benchmark                   Mode  Cnt    Score   Error  Units
[info] ArrayBench.arrMap           avgt   20   83.480 ± 0.525  us/op
[info] ArrayBench.arrMapFilter     avgt   20  108.305 ± 1.329  us/op
[info] ArrayBench.arrMapFilterMap  avgt   20  143.501 ± 1.688  us/op
[info] ArrayBench.arrMapMap        avgt   20  176.429 ± 1.841  us/op

// 2.11.8 (with boxed array)
[info] Benchmark                   Mode  Cnt    Score   Error  Units
[info] ArrayBench.arrMap           avgt   20   58.183 ± 0.747  us/op // faster
[info] ArrayBench.arrMapFilter     avgt   20  150.008 ± 1.056  us/op // slower 
[info] ArrayBench.arrMapFilterMap  avgt   20  197.817 ± 2.061  us/op // slower
[info] ArrayBench.arrMapMap        avgt   20  199.428 ± 2.548  us/op // slower
// 2.12.8 (without boxed array)
[info] Benchmark                   Mode  Cnt    Score   Error  Units
[info] ArrayBench.arrMap           avgt   20   78.241 ± 0.520  us/op
[info] ArrayBench.arrMapFilter     avgt   20  102.357 ± 1.294  us/op
[info] ArrayBench.arrMapFilterMap  avgt   20  129.575 ± 1.035  us/op
[info] ArrayBench.arrMapMap        avgt   20  167.233 ± 2.923  us/op

// 2.12.8 (with boxed array)
[info] Benchmark                   Mode  Cnt    Score    Error  Units
[info] ArrayBench.arrMap           avgt   20   52.152 ±  0.506  us/op // faster 
[info] ArrayBench.arrMapFilter     avgt   20  148.799 ±  1.266  us/op // slower 
[info] ArrayBench.arrMapFilterMap  avgt   20  199.924 ±  1.883  us/op // slower
[info] ArrayBench.arrMapMap        avgt   20  198.048 ± 13.489  us/op // slower
package benchmarks

import java.util.concurrent.TimeUnit

import org.openjdk.jmh.annotations._

@BenchmarkMode(Array(Mode.AverageTime))
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
class ArrayBench {
  // case class BoxedInt(i: Int)
  // var arr2: Array[BoxedInt] = _
  var arr1: Array[Int] = _

  @Setup
  def setup: Unit = {
    // arr2 = Array.range(10000, 1, -1).map(BoxedInt)
    arr1 = Array.range(10000, 1, -1)
  }

  @Benchmark
  def arrMap: Array[Int] = arr1.map(_ + 1)

  @Benchmark
  def arrMapMap: Array[Int] = arr1.map(_ + 1).map(_ * 2)

  @Benchmark
  def arrMapFilter: Array[Int] = arr1.map(_ + 1).filter(_ % 2 == 0)

  @Benchmark
  def arrMapFilterMap: Array[Int] = arr1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2)
}
...