Skip to content

Instantly share code, notes, and snippets.

@TheDIM47
Created August 28, 2021 17:55
Show Gist options
  • Save TheDIM47/c9def0e39b2014a07b22d770baad87a3 to your computer and use it in GitHub Desktop.
Save TheDIM47/c9def0e39b2014a07b22d770baad87a3 to your computer and use it in GitHub Desktop.
flatten benchmarks
package benchmarks
import org.openjdk.jmh.annotations._
import scala.util.Random
import java.util.concurrent.TimeUnit
import scala.annotation.tailrec
/*
[info] Benchmark (size) Mode Cnt Score Error Units
[info] EffFlattenBenchmark.benchEffFlatten 50 thrpt 5 2981.439 ± 165.839 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten 100 thrpt 5 1438.206 ± 24.179 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten 500 thrpt 5 321.286 ± 9.320 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Builder 50 thrpt 5 2907.176 ± 26.562 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Builder 100 thrpt 5 1553.765 ± 33.479 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Builder 500 thrpt 5 297.438 ± 9.401 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Collect 50 thrpt 5 4899.624 ± 126.770 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Collect 100 thrpt 5 2630.149 ± 35.264 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Collect 500 thrpt 5 511.721 ± 8.355 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldLeftBuilder 50 thrpt 5 2817.795 ± 79.083 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldLeftBuilder 100 thrpt 5 1437.505 ± 33.103 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldLeftBuilder 500 thrpt 5 285.858 ± 9.366 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldLeftList 50 thrpt 5 4281.285 ± 97.378 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldLeftList 100 thrpt 5 2303.624 ± 36.768 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldLeftList 500 thrpt 5 320.638 ± 2.261 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldRightList 50 thrpt 5 2894.644 ± 79.858 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldRightList 100 thrpt 5 1450.015 ± 45.743 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_FoldRightList 500 thrpt 5 274.268 ± 8.043 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_NoReverse 50 thrpt 5 4503.200 ± 88.736 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_NoReverse 100 thrpt 5 2356.487 ± 80.884 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_NoReverse 500 thrpt 5 462.636 ± 7.592 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Raw 50 thrpt 5 2987.859 ± 76.475 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Raw 100 thrpt 5 1350.700 ± 27.003 ops/ms
[info] EffFlattenBenchmark.benchEffFlatten_Raw 500 thrpt 5 309.497 ± 7.093 ops/ms
*/
@State(Scope.Thread)
@BenchmarkMode(Array(Mode.Throughput))
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(1)
class EffFlattenBenchmark {
var list: List[Option[Int]] = _
@Param(Array("50", "100", "500"))
var size: Int = _
@Setup(Level.Trial)
def setup(): Unit =
list = (1 to size)
.map(_ => {
val r = Random.nextInt()
if (r % 3 == 0) None else Some(r)
})
.toList
@tailrec
final def effFlatten[T](l: List[Option[T]], acc: List[T]): List[T] =
l match {
case Nil => acc.reverse // а нужен ли reverse() ?
case Some(h) :: tail => effFlatten(tail, h :: acc)
case None :: tail => effFlatten(tail, acc)
}
final def effFlatten[T](l: List[Option[T]]): List[T] = {
@tailrec
def goFlatten(l: List[Option[T]], acc: List[T]): List[T] =
l match {
case Nil => acc.reverse // а нужен ли reverse() ?
case Some(h) :: tail => goFlatten(tail, h :: acc)
case None :: tail => goFlatten(tail, acc)
}
goFlatten(l, Nil)
}
final def effFlattenNoReverse[T](l: List[Option[T]]): List[T] = {
@tailrec
def goFlatten(l: List[Option[T]], acc: List[T]): List[T] =
l match {
case Nil => acc
case Some(h) :: tail => goFlatten(tail, h :: acc)
case None :: tail => goFlatten(tail, acc)
}
goFlatten(l, Nil)
}
final def effFlattenFoldRightList[T](l: List[Option[T]]): List[T] =
l.foldRight(Nil: List[T])((a, acc) => a.fold(acc)(_ :: acc))
final def effFlattenFoldLeftList[T](l: List[Option[T]]): List[T] =
l.foldLeft(Nil: List[T])((acc, a) => a.fold(acc)(_ :: acc))
final def effFlattenFoldLeftBuilder[T](l: List[Option[T]]): List[T] =
l.foldLeft(List.newBuilder[T])((acc, a) => a.fold(acc)(acc.addOne)).result()
final def effFlattenCollect[T](l: List[Option[T]]): List[T] =
l.collect { case Some(a) => a }
final def effFlattenBuilder[T](l: List[Option[T]]): List[T] = {
val builder = List.newBuilder[T]
l.foreach(_.foreach(builder.addOne))
builder.result()
}
@Benchmark def benchEffFlatten_Raw: List[Int] = effFlatten[Int](list, Nil)
@Benchmark def benchEffFlatten_FoldLeftBuilder: List[Int] = effFlattenFoldLeftBuilder[Int](list)
@Benchmark def benchEffFlatten_Builder: List[Int] = effFlattenBuilder[Int](list)
@Benchmark def benchEffFlatten_Collect: List[Int] = effFlattenCollect[Int](list)
@Benchmark def benchEffFlatten: List[Int] = effFlatten[Int](list)
@Benchmark def benchEffFlatten_NoReverse: List[Int] = effFlattenNoReverse[Int](list)
@Benchmark def benchEffFlatten_FoldRightList: List[Int] = effFlattenFoldRightList[Int](list)
@Benchmark def benchEffFlatten_FoldLeftList: List[Int] = effFlattenFoldLeftList[Int](list)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment