Какой из них является более производительным с точки зрения процессора. `Option.fold () ()` или `Option.map (). GetOrElse ()`? - PullRequest
0 голосов
/ 10 января 2020

Я пытаюсь в терминах time per op узнать, какой метод быстрее.

Инстинктивно, я бы сказал, что fold быстрее, поскольку "кажется" не создает дополнительных Option, ср. реализация:

@inline final def fold[B](ifEmpty: => B)(f: A => B): B =
  if (isEmpty) ifEmpty else f(this.get)
@inline final def map[B](f: A => B): Option[B] =
  if (isEmpty) None else Some(f(this.get))

Однако я попытался профилировать, используя jmh для профилирования allocation rate и time, используя следующий код:

import java.util.concurrent.TimeUnit
import org.openjdk.jmh.annotations._

@State(Scope.Benchmark)
@BenchmarkMode(Array(Mode.AverageTime))
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 1, jvmArgsAppend = Array("-Djmh.stack.lines=3"))
@Threads(1)
@Warmup(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS)
class OptionBench {
  val someOption = Some(2)
  val noneOption = None

  def fold(option: Option[Int]) = option.fold(0)(_ * 2)

  def map(option: Option[Int]) = option.map(_ * 2).getOrElse(0)

  @Benchmark
  def someNothing = someOption

  @Benchmark
  def someFold = fold(someOption)

  @Benchmark
  def noneFold = fold(noneOption)

  @Benchmark
  def someMap = map(someOption)

  @Benchmark
  def noneMap = map(noneOption)
}

Я получил следующее Результаты:

Benchmark                                    Mode  Cnt   Score    Error   Units
OptionBench.noneFold                         avgt    5   2,214 ±  0,068   ns/op
OptionBench.noneFold:·gc.alloc.rate          avgt    5  ≈ 10⁻⁴           MB/sec
OptionBench.noneFold:·gc.alloc.rate.norm     avgt    5  ≈ 10⁻⁶             B/op
OptionBench.noneFold:·gc.count               avgt    5     ≈ 0           counts
OptionBench.noneMap                          avgt    5   2,373 ±  0,106   ns/op
OptionBench.noneMap:·gc.alloc.rate           avgt    5  ≈ 10⁻⁴           MB/sec
OptionBench.noneMap:·gc.alloc.rate.norm      avgt    5  ≈ 10⁻⁶             B/op
OptionBench.noneMap:·gc.count                avgt    5     ≈ 0           counts
OptionBench.someFold                         avgt    5   3,183 ±  0,282   ns/op
OptionBench.someFold:·gc.alloc.rate          avgt    5  ≈ 10⁻⁴           MB/sec
OptionBench.someFold:·gc.alloc.rate.norm     avgt    5  ≈ 10⁻⁶             B/op
OptionBench.someFold:·gc.count               avgt    5     ≈ 0           counts
OptionBench.someMap                          avgt    5   2,994 ±  0,181   ns/op
OptionBench.someMap:·gc.alloc.rate           avgt    5  ≈ 10⁻⁴           MB/sec
OptionBench.someMap:·gc.alloc.rate.norm      avgt    5  ≈ 10⁻⁶             B/op
OptionBench.someMap:·gc.count                avgt    5     ≈ 0           counts
OptionBench.someNothing                      avgt    5   2,258 ±  0,085   ns/op
OptionBench.someNothing:·gc.alloc.rate       avgt    5  ≈ 10⁻⁴           MB/sec
OptionBench.someNothing:·gc.alloc.rate.norm  avgt    5  ≈ 10⁻⁶             B/op
OptionBench.someNothing:·gc.count            avgt    5     ≈ 0           counts

К сожалению, я не могу сделать какие-либо выводы из этого. Я неправильно делаю свое профилирование? Какой из них "быстрее"?

...