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