Scala `.sum` производительность при выполнении туда и обратно - PullRequest
0 голосов
/ 04 апреля 2020

У меня есть очень простой код

  val things: Seq[Long] = (1L to 100000000L)
  val start: Long = System.nanoTime()
  val result = things.sum
  val end: Long = System.nanoTime()
  println(end-start)

, который печатает что-то вроде 1790900, примерно 2 мс.

Однако, когда я представляю свой класс кейсов

case class Thing(foo: Long) extends AnyVal

кажется, это меняет все. Ты мне не веришь? Просто смотреть. Я сопоставлю свою последовательность длин с Thing с и обратно с последовательностью длин:

  val things: Seq[Long] = (1L to 100000000L).map(i => Thing(i)).map(t => t.foo)
  val start: Long = System.nanoTime()
  val result = things.sum
  val end: Long = System.nanoTime()
  println(end-start)

Теперь эталонный тест имеет порядок 1058361600.

Как это возможно?

Когда

Ответы [ 2 ]

5 голосов
/ 04 апреля 2020

Во-первых, вы не получите разумную информацию о синхронизации при первом запуске, вам нужно будет запустить ее несколько раз, чтобы JIT-компилятор оптимизировал код.

Но проблема здесь в том, что Range is lazy , а (1L to 100000000L) просто записывает начальное и конечное значения, но не выделяет вектор с 100000000 элементов. Поэтому, когда вы звоните sum, Range просто доставляет каждое число по очереди для сложения вместе вычисляет значение непосредственно **.

Вторая версия создает огромный список Long значений, а затем складывает их, что будет намного, намного медленнее.


** Спасибо Йоргу Миттагу за подсказку, что Range имеет перегруженную реализацию sum .

4 голосов
/ 04 апреля 2020

Чтобы проиллюстрировать точку зрения Тима, здесь приведено сравнение jmh с

case class Thing(foo: Long) extends AnyVal

@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.Throughput))
class So61032621 {
  val size = 100000000L
  val as = 1L to size
  val bs = (1L to size).map(i => Thing(i)).map(t => t.foo)
  @Benchmark def a: Long = as.sum
  @Benchmark def b: Long = bs.sum
}

, где sbt "jmh:run -i 5 -wi 5 -f 1 -t 1 -prof gc bench.So61032621" дает

Benchmark                                       Mode  Cnt           Score           Error   Units
So61032621.a                                   thrpt    5    53677138.590 ±   9550110.580   ops/s
So61032621.a:·gc.alloc.rate                    thrpt    5        4679.263 ±       831.014  MB/sec
So61032621.a:·gc.alloc.rate.norm               thrpt    5          96.000 ±         0.001    B/op
So61032621.a:·gc.churn.PS_Eden_Space           thrpt    5        4690.565 ±       773.522  MB/sec
So61032621.a:·gc.churn.PS_Eden_Space.norm      thrpt    5          96.252 ±         5.062    B/op
So61032621.a:·gc.churn.PS_Survivor_Space       thrpt    5           0.046 ±         0.019  MB/sec
So61032621.a:·gc.churn.PS_Survivor_Space.norm  thrpt    5           0.001 ±         0.001    B/op
So61032621.a:·gc.count                         thrpt    5         177.000                  counts
So61032621.a:·gc.time                          thrpt    5         434.000                      ms
So61032621.b                                   thrpt    5           1.043 ±         0.039   ops/s
So61032621.b:·gc.alloc.rate                    thrpt    5        2277.815 ±        81.170  MB/sec
So61032621.b:·gc.alloc.rate.norm               thrpt    5  2399999759.273 ±         0.001    B/op
So61032621.b:·gc.churn.PS_Eden_Space           thrpt    5        2266.218 ±       138.781  MB/sec
So61032621.b:·gc.churn.PS_Eden_Space.norm      thrpt    5  2387779137.164 ± 117864918.226    B/op
So61032621.b:·gc.churn.PS_Survivor_Space       thrpt    5           0.048 ±         0.028  MB/sec
So61032621.b:·gc.churn.PS_Survivor_Space.norm  thrpt    5       50641.455 ±     29244.708    B/op
So61032621.b:·gc.count                         thrpt    5         116.000                  counts
So61032621.b:·gc.time                          thrpt    5         287.000                      ms

Обратите внимание на разницу c в скоростях выделения памяти

So61032621.a:·gc.alloc.rate.norm               thrpt    5          96.000 ±         0.001    B/op
So61032621.b:·gc.alloc.rate.norm               thrpt    5  2399999759.273 ±         0.001    B/op
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...