diff --git a/build.sbt b/build.sbt index e7fcc28..fa45281 100644 --- a/build.sbt +++ b/build.sbt @@ -2,21 +2,20 @@ name := """scala-benchmarks""" version := "1.0.0" -scalaVersion := "2.12.6" +scalaVersion := "2.13.0-M5" scalacOptions := Seq( "-opt:l:inline", "-opt-inline-from:**", "-deprecation", - "-Ypartial-unification", "-Ywarn-value-discard", - "-Ywarn-unused-import", "-Ywarn-dead-code", "-Ywarn-numeric-widen" ) libraryDependencies ++= Seq( - "org.scalaz" %% "scalaz-core" % "7.2.24" + "org.typelevel" %% "cats-core" % "1.6.0", + "org.scalaz" %% "scalaz-core" % "7.2.27" ) /* To run benchmarks: diff --git a/project/build.properties b/project/build.properties index 64cf32f..c0bab04 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.1.4 +sbt.version=1.2.8 diff --git a/project/plugins.sbt b/project/plugins.sbt index be94ef1..a12e17f 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1 +1 @@ -addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.3.3") +addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.3.4") diff --git a/src/main/scala/benchmarks/AccumClassBench.scala b/src/main/scala/benchmarks/AccumClassBench.scala index f0a6221..17d6f74 100644 --- a/src/main/scala/benchmarks/AccumClassBench.scala +++ b/src/main/scala/benchmarks/AccumClassBench.scala @@ -6,6 +6,7 @@ import scala.annotation.tailrec import scala.collection.immutable.VectorBuilder import scala.collection.mutable.{ArrayBuilder, ListBuffer} +import cats.data.Chain import org.openjdk.jmh.annotations._ import scalaz.{IList, ICons, INil} @@ -98,6 +99,15 @@ class AccumClassBench { b.result } + def chain(n: Int): Chain[Pair] = { + + @tailrec def work(acc: Chain[Pair], m: Int): Chain[Pair] = m match { + case _ if m == n => acc + case _ => work(Pair(m, m) +: acc, m + 1) + } + work(Chain.empty[Pair], 0) + } + def foryield(n: Int): IndexedSeq[Pair] = for (i <- 0 to n) yield Pair(i, i) @Benchmark @@ -149,11 +159,17 @@ class AccumClassBench { @Benchmark def buffer100000: List[Pair] = buffer(100000) + @Benchmark + def chain1000: Chain[Pair] = chain(1000) + @Benchmark + def chain10000: Chain[Pair] = chain(10000) + @Benchmark + def chain100000: Chain[Pair] = chain(100000) + @Benchmark def foryield1000: IndexedSeq[Pair] = foryield(1000) @Benchmark def foryield10000: IndexedSeq[Pair] = foryield(10000) @Benchmark def foryield100000: IndexedSeq[Pair] = foryield(100000) - } diff --git a/src/main/scala/benchmarks/ConcatBench.scala b/src/main/scala/benchmarks/ConcatBench.scala index 4badd02..4e5fcfb 100644 --- a/src/main/scala/benchmarks/ConcatBench.scala +++ b/src/main/scala/benchmarks/ConcatBench.scala @@ -2,6 +2,7 @@ package benchmarks import java.util.concurrent.TimeUnit +import cats.data.Chain import org.openjdk.jmh.annotations._ import scalaz.{IList, EphemeralStream => EStream} @@ -57,14 +58,14 @@ class ConcatBench { var arrayC2b: Array[Pair] = _ var arrayC3b: Array[Pair] = _ - var stream0: Stream[Int] = _ - var stream1: Stream[Int] = _ - var stream2: Stream[Int] = _ - var stream3: Stream[Int] = _ - var stream0b: Stream[Int] = _ - var stream1b: Stream[Int] = _ - var stream2b: Stream[Int] = _ - var stream3b: Stream[Int] = _ + var lazyList0: LazyList[Int] = _ + var lazyList1: LazyList[Int] = _ + var lazyList2: LazyList[Int] = _ + var lazyList3: LazyList[Int] = _ + var lazyList0b: LazyList[Int] = _ + var lazyList1b: LazyList[Int] = _ + var lazyList2b: LazyList[Int] = _ + var lazyList3b: LazyList[Int] = _ var estream0: EStream[Int] = _ var estream1: EStream[Int] = _ @@ -75,6 +76,15 @@ class ConcatBench { var estream2b: EStream[Int] = _ var estream3b: EStream[Int] = _ + var chain0: Chain[Int] = _ + var chain1: Chain[Int] = _ + var chain2: Chain[Int] = _ + var chain3: Chain[Int] = _ + var chain0b: Chain[Int] = _ + var chain1b: Chain[Int] = _ + var chain2b: Chain[Int] = _ + var chain3b: Chain[Int] = _ + @Setup def setup: Unit = { list0 = List.range(1, 1000) @@ -122,14 +132,14 @@ class ConcatBench { arrayC2b = Array.range(1, 100000).map(n => Pair(n, n)) arrayC3b = Array.range(1, 1000000).map(n => Pair(n, n)) - stream0 = Stream.range(1, 1000) - stream1 = Stream.range(1, 10000) - stream2 = Stream.range(1, 100000) - stream3 = Stream.range(1, 1000000) - stream0b = Stream.range(1, 1000) - stream1b = Stream.range(1, 10000) - stream2b = Stream.range(1, 100000) - stream3b = Stream.range(1, 1000000) + lazyList0 = LazyList.range(1, 1000) + lazyList1 = LazyList.range(1, 10000) + lazyList2 = LazyList.range(1, 100000) + lazyList3 = LazyList.range(1, 1000000) + lazyList0b = LazyList.range(1, 1000) + lazyList1b = LazyList.range(1, 10000) + lazyList2b = LazyList.range(1, 100000) + lazyList3b = LazyList.range(1, 1000000) estream0 = EStream.range(1, 1000) estream1 = EStream.range(1, 10000) @@ -139,6 +149,15 @@ class ConcatBench { estream1b = EStream.range(1, 10000) estream2b = EStream.range(1, 100000) estream3b = EStream.range(1, 1000000) + + chain0 = Chain.fromSeq(list0) + chain1 = Chain.fromSeq(list1) + chain2 = Chain.fromSeq(list2) + chain3 = Chain.fromSeq(list3) + chain0b = Chain.fromSeq(list0) + chain1b = Chain.fromSeq(list1) + chain2b = Chain.fromSeq(list2) + chain3b = Chain.fromSeq(list3) } def list(a: List[Int], b: List[Int]): List[Int] = a ++ b @@ -146,8 +165,9 @@ class ConcatBench { def vector(a: Vector[Int], b: Vector[Int]): Vector[Int] = a ++ b def array(a: Array[Int], b: Array[Int]): Array[Int] = a ++ b def arrayC(a: Array[Pair], b: Array[Pair]): Array[Pair] = a ++ b - def stream(a: Stream[Int], b: Stream[Int]): Stream[Int] = a ++ b + def lazyList(a: LazyList[Int], b: LazyList[Int]): LazyList[Int] = a ++ b def estream(a: EStream[Int], b: EStream[Int]): EStream[Int] = a ++ b + def chain(a: Chain[Int], b: Chain[Int]): Chain[Int] = a ++ b @Benchmark def list1k: List[Int] = list(list0, list0b) @@ -195,13 +215,13 @@ class ConcatBench { def arrayC1000k: Array[Pair] = arrayC(arrayC3 , arrayC3b) @Benchmark - def stream1k: Stream[Int] = stream(stream0 , stream0b) + def lazyList1k: LazyList[Int] = lazyList(lazyList0 , lazyList0b) @Benchmark - def stream10k: Stream[Int] = stream(stream1 , stream1b) + def lazyList10k: LazyList[Int] = lazyList(lazyList1 , lazyList1b) @Benchmark - def stream100k: Stream[Int] = stream(stream2 , stream2b) + def lazyList100k: LazyList[Int] = lazyList(lazyList2 , lazyList2b) @Benchmark - def stream1000k: Stream[Int] = stream(stream3 , stream3b) + def lazyList1000k: LazyList[Int] = lazyList(lazyList3 , lazyList3b) @Benchmark def estream1k: EStream[Int] = estream(estream0 , estream0b) @@ -211,4 +231,13 @@ class ConcatBench { def estream100k: EStream[Int] = estream(estream2 , estream2b) @Benchmark def estream1000k: EStream[Int] = estream(estream3 , estream3b) + + @Benchmark + def chain1k: Chain[Int] = chain(chain0 , chain0b) + @Benchmark + def chain10k: Chain[Int] = chain(chain1 , chain1b) + @Benchmark + def chain100k: Chain[Int] = chain(chain2 , chain2b) + @Benchmark + def chain1000k: Chain[Int] = chain(chain3 , chain3b) } diff --git a/src/main/scala/benchmarks/FoldBench.scala b/src/main/scala/benchmarks/FoldBench.scala index fa572c6..bf12e93 100644 --- a/src/main/scala/benchmarks/FoldBench.scala +++ b/src/main/scala/benchmarks/FoldBench.scala @@ -4,6 +4,7 @@ import java.util.concurrent.TimeUnit import scala.annotation.tailrec +import cats.data.Chain import org.openjdk.jmh.annotations._ import scalaz.{IList, ICons, INil, EphemeralStream => EStream} @@ -18,8 +19,9 @@ class FoldBench { var ilist: IList[Int] = _ var vector: Vector[Int] = _ var array: Array[Int] = _ - var stream: Stream[Int] = _ + var lazyList: LazyList[Int] = _ var estream: EStream[Int] = _ + var chain: Chain[Int] = _ @Setup def setup: Unit = { @@ -27,8 +29,9 @@ class FoldBench { ilist = IList.fromList(list) vector = Vector.range(1, 10000) array = Array.range(1, 10000) - stream = Stream.range(1, 10000) + lazyList = LazyList.range(1, 10000) estream = EStream.range(1, 10000) + chain = Chain.fromSeq(list) } @Benchmark @@ -128,22 +131,22 @@ class FoldBench { def arraySum: Int = array.sum @Benchmark - def streamFoldLeft: Int = stream.foldLeft(0)(_ + _) + def lazyListFoldLeft: Int = lazyList.foldLeft(0)(_ + _) @Benchmark - def streamFoldRight: Int = stream.foldRight(0)(_ + _) + def lazyListFoldRight: Int = lazyList.foldRight(0)(_ + _) @Benchmark - def streamTailrec: Int = { - @tailrec def work(l: Stream[Int], acc: Int): Int = l match { + def lazyListTailrec: Int = { + @tailrec def work(l: LazyList[Int], acc: Int): Int = l match { case _ if l.isEmpty => acc case h #:: rest => work(rest, h + acc) } - work(stream, 0) + work(lazyList, 0) } @Benchmark - def streamWhile: Int = { + def lazyListWhile: Int = { var i: Int = 0 - var l: Stream[Int] = stream + var l: LazyList[Int] = lazyList while (!l.isEmpty) { i += l.head @@ -153,10 +156,38 @@ class FoldBench { i } @Benchmark - def streamSum: Int = stream.sum + def lazyListSum: Int = lazyList.sum @Benchmark def estreamFoldLeft: Int = estream.foldLeft(0) { acc => { n => acc + n } } @Benchmark def estreamFoldRight: Int = estream.foldRight(0) { n => { acc => n + acc } } + + @Benchmark + def chainFoldLeft: Int = chain.foldLeft(0)(_ + _) + @Benchmark + def chainFoldRight: Int = chain.foldRight(0)(_ + _) + @Benchmark + def chainTailrec: Int = { + @tailrec def work(l: Chain[Int], acc: Int): Int = l.uncons match { + case None => acc + case Some((h, rest)) => work(rest, h + acc) + } + + work(chain, 0) + } + @Benchmark + def chainWhile: Int = { + var i: Int = 0 + var l: Chain[Int] = chain + var uc = l.uncons + + while (!uc.isEmpty) { + i += uc.get._1 + l = uc.get._2 + uc = l.uncons + } + + i + } } diff --git a/src/main/scala/benchmarks/FoldClassBench.scala b/src/main/scala/benchmarks/FoldClassBench.scala index dce3d3d..a414542 100644 --- a/src/main/scala/benchmarks/FoldClassBench.scala +++ b/src/main/scala/benchmarks/FoldClassBench.scala @@ -4,6 +4,7 @@ import java.util.concurrent.TimeUnit import scala.annotation.tailrec +import cats.data.Chain import org.openjdk.jmh.annotations._ import scalaz.{IList, ICons, INil} @@ -18,7 +19,8 @@ class FoldClassBench { var ilist: IList[Pair] = _ var vector: Vector[Pair] = _ var array: Array[Pair] = _ - var stream: Stream[Pair] = _ + var lazyList: LazyList[Pair] = _ + var chain: Chain[Pair] = _ @Setup def setup: Unit = { @@ -26,7 +28,8 @@ class FoldClassBench { ilist = IList.fromList(list) vector = Vector.range(1, 10000).map(n => Pair(n, n)) array = Array.range(1, 10000).map(n => Pair(n, n)) - stream = Stream.range(1, 10000).map(n => Pair(n, n)) + lazyList = LazyList.range(1, 10000).map(n => Pair(n, n)) + chain = Chain.fromSeq(list) } @Benchmark @@ -120,22 +123,22 @@ class FoldClassBench { } @Benchmark - def streamFoldLeft: Pair = stream.foldLeft(Pair(0,0))(_ + _) + def lazyListFoldLeft: Pair = lazyList.foldLeft(Pair(0,0))(_ + _) @Benchmark - def streamFoldRight: Pair = stream.foldRight(Pair(0,0))(_ + _) + def lazyListFoldRight: Pair = lazyList.foldRight(Pair(0,0))(_ + _) @Benchmark - def streamTailrec: Pair = { - @tailrec def work(l: Stream[Pair], acc: Pair): Pair = l match { + def lazyListTailrec: Pair = { + @tailrec def work(l: LazyList[Pair], acc: Pair): Pair = l match { case _ if l.isEmpty => acc case h #:: rest => work(rest, h + acc) } - work(stream, Pair(0,0)) + work(lazyList, Pair(0,0)) } @Benchmark - def streamWhile: Pair = { + def lazyListWhile: Pair = { var i: Pair = Pair(0,0) - var l: Stream[Pair] = stream + var l: LazyList[Pair] = lazyList while (!l.isEmpty) { i = i + l.head @@ -145,4 +148,31 @@ class FoldClassBench { i } + @Benchmark + def chainFoldLeft: Pair = chain.foldLeft(Pair(0,0))(_ + _) + @Benchmark + def chainFoldRight: Pair = chain.foldRight(Pair(0,0))(_ + _) + @Benchmark + def chainTailrec: Pair = { + @tailrec def work(l: Chain[Pair], acc: Pair): Pair = l.uncons match { + case None => acc + case Some((h, rest)) => work(rest, h + acc) + } + + work(chain, Pair(0,0)) + } + @Benchmark + def chainWhile: Pair = { + var i: Pair = Pair(0,0) + var l: Chain[Pair] = chain + var uc = l.uncons + + while (!uc.isEmpty) { + i += uc.get._1 + l = uc.get._2 + uc = l.uncons + } + + i + } } diff --git a/src/main/scala/benchmarks/MapBench.scala b/src/main/scala/benchmarks/MapBench.scala index dfd58b4..b2c459d 100644 --- a/src/main/scala/benchmarks/MapBench.scala +++ b/src/main/scala/benchmarks/MapBench.scala @@ -2,6 +2,7 @@ package benchmarks import java.util.concurrent.TimeUnit +import cats.data.Chain import org.openjdk.jmh.annotations._ import scalaz.IList @@ -21,6 +22,9 @@ class MapBench { var array0: Array[Int] = _ var array1: Array[Int] = _ var array2: Array[Int] = _ + var chain0: Chain[Int] = _ + var chain1: Chain[Int] = _ + var chain2: Chain[Int] = _ var listC0: List[Pair] = _ var listC1: List[Pair] = _ @@ -31,6 +35,9 @@ class MapBench { var arrayC0: Array[Pair] = _ var arrayC1: Array[Pair] = _ var arrayC2: Array[Pair] = _ + var chainC0: Chain[Pair] = _ + var chainC1: Chain[Pair] = _ + var chainC2: Chain[Pair] = _ @Setup def setup: Unit = { @@ -43,6 +50,9 @@ class MapBench { array0 = Array.range(1, 100) array1 = Array.range(1, 1000) array2 = Array.range(1, 10000) + chain0 = Chain.fromSeq(list0) + chain1 = Chain.fromSeq(list1) + chain2 = Chain.fromSeq(list2) listC0 = list0.map(n => Pair(n, n)) listC1 = list1.map(n => Pair(n, n)) @@ -53,6 +63,9 @@ class MapBench { arrayC0 = array0.map(n => Pair(n, n)) arrayC1 = array1.map(n => Pair(n, n)) arrayC2 = array2.map(n => Pair(n, n)) + chainC0 = chain0.map(n => Pair(n, n)) + chainC1 = chain1.map(n => Pair(n, n)) + chainC2 = chain2.map(n => Pair(n, n)) } def arrayWhile(arr: Array[Int]): Array[Int] = { @@ -88,6 +101,10 @@ class MapBench { def ilistMapClass(l: IList[Pair]): IList[Pair] = l.map { case Pair(c, r) => Pair(c * 37, r * 37) } + def chainMap(l: Chain[Int]): Chain[Int] = l.map(_ * 37) + + def chainMapClass(l: Chain[Pair]): Chain[Pair] = l.map { case Pair(c, r) => Pair(c * 37, r * 37) } + @Benchmark def list100: List[Int] = listMap(list0) @Benchmark @@ -130,4 +147,17 @@ class MapBench { @Benchmark def arrayClass10000: Array[Pair] = arrayWhileClass(arrayC2) + @Benchmark + def chain100: Chain[Int] = chainMap(chain0) + @Benchmark + def chain1000: Chain[Int] = chainMap(chain1) + @Benchmark + def chain10000: Chain[Int] = chainMap(chain2) + + @Benchmark + def chainClass100: Chain[Pair] = chainMapClass(chainC0) + @Benchmark + def chainClass1000: Chain[Pair] = chainMapClass(chainC1) + @Benchmark + def chainClass10000: Chain[Pair] = chainMapClass(chainC2) } diff --git a/src/main/scala/benchmarks/MatchContainersBench.scala b/src/main/scala/benchmarks/MatchContainersBench.scala index 5c66248..355a8d9 100644 --- a/src/main/scala/benchmarks/MatchContainersBench.scala +++ b/src/main/scala/benchmarks/MatchContainersBench.scala @@ -4,6 +4,7 @@ import java.util.concurrent.TimeUnit import scala.annotation.tailrec +import cats.data.Chain import org.openjdk.jmh.annotations._ import scalaz.{IList, ICons, INil} @@ -19,7 +20,8 @@ class MatchContainersBench { var vec: Vector[Int] = _ var arr: Array[Int] = _ var seq: Seq[Int] = _ - var stream: Stream[Int] = _ + var lazyList: LazyList[Int] = _ + var chain: Chain[Int] = _ @Setup def setup: Unit = { @@ -28,7 +30,8 @@ class MatchContainersBench { vec = Vector.range(1, 10000) arr = Array.range(1, 10000) seq = Seq.range(1, 10000) - stream = Stream.range(1, 10000) + lazyList = LazyList.range(1, 10000) + chain = Chain.fromSeq(list) } @Benchmark @@ -141,30 +144,30 @@ class MatchContainersBench { } @Benchmark - def lastStreamMatch: Option[Int] = { - @tailrec def work(l: Stream[Int]): Option[Int] = l match { - case Stream() => None - case h #:: Stream() => Some(h) + def lastLazyListMatch: Option[Int] = { + @tailrec def work(l: LazyList[Int]): Option[Int] = l match { + case LazyList() => None + case h #:: LazyList() => Some(h) case _ #:: rest => work(rest) } - work(stream) + work(lazyList) } @Benchmark - def lastStreamMatchGeneric: Option[Int] = { - @tailrec def work(l: Stream[Int]): Option[Int] = l match { - case Stream() => None - case h +: Stream() => Some(h) + def lastLazyListMatchGeneric: Option[Int] = { + @tailrec def work(l: LazyList[Int]): Option[Int] = l match { + case LazyList() => None + case h +: LazyList() => Some(h) case _ +: rest => work(rest) } - work(stream) + work(lazyList) } @Benchmark - def lastStreamIf: Option[Int] = { - @tailrec def work(l: Stream[Int]): Option[Int] = { + def lastLazyListIf: Option[Int] = { + @tailrec def work(l: LazyList[Int]): Option[Int] = { if (l.isEmpty) { None } else { val t = l.tail @@ -172,7 +175,41 @@ class MatchContainersBench { } } - work(stream) + work(lazyList) } + @Benchmark + def lastChainMatch: Option[Int] = { + @tailrec def work(l: Chain[Int]): Option[Int] = l.uncons match { + case None => None + case Some((h, t)) if t.isEmpty => Some(h) + case Some((_, rest)) => work(rest) + } + + work(chain) + } + + @Benchmark + def lastChainMatchGeneric: Option[Int] = { + @tailrec def work(l: Chain[Int]): Option[Int] = l match { + case _ if l.isEmpty => None + case (h: Int) +: t if t.isEmpty => Some(h) + case _ +: (rest: Chain[Int]) => work(rest) + } + + work(chain) + } + + @Benchmark + def lastChainIf: Option[Int] = { + @tailrec def work(l: Chain[Int]): Option[Int] = { + if (l.isEmpty) { None } + else { + val (h, t) = l.uncons.get + if (t.isEmpty) Some(h) else work(t) + } + } + + work(chain) + } } diff --git a/src/main/scala/benchmarks/SortBench.scala b/src/main/scala/benchmarks/SortBench.scala index acfc8f0..917618f 100644 --- a/src/main/scala/benchmarks/SortBench.scala +++ b/src/main/scala/benchmarks/SortBench.scala @@ -35,11 +35,11 @@ class SortBench { } @Benchmark - def sortStream0: Stream[Int] = Stream.range(1, 1000).sorted + def sortLazyList0: LazyList[Int] = LazyList.range(1, 1000).sorted @Benchmark - def sortStream1: Stream[Int] = Stream.range(1, 10000).sorted + def sortLazyList1: LazyList[Int] = LazyList.range(1, 10000).sorted @Benchmark - def sortStream2: Stream[Int] = Stream.range(1, 100000).sorted + def sortLazyList2: LazyList[Int] = LazyList.range(1, 100000).sorted @Benchmark def sortList0: List[Int] = list0.sorted @@ -93,11 +93,11 @@ class BackwardSortBench { } @Benchmark - def sortStream0: Stream[Int] = Stream.range(1000, 1, -1).sorted + def sortLazyList0: LazyList[Int] = LazyList.range(1000, 1, -1).sorted @Benchmark - def sortStream1: Stream[Int] = Stream.range(10000, 1, -1).sorted + def sortLazyList1: LazyList[Int] = LazyList.range(10000, 1, -1).sorted @Benchmark - def sortStream2: Stream[Int] = Stream.range(100000, 1, -1).sorted + def sortLazyList2: LazyList[Int] = LazyList.range(100000, 1, -1).sorted @Benchmark def sortList0: List[Int] = list0.sorted diff --git a/src/main/scala/benchmarks/StreamBench.scala b/src/main/scala/benchmarks/StreamBench.scala index d83cf3f..30cab71 100644 --- a/src/main/scala/benchmarks/StreamBench.scala +++ b/src/main/scala/benchmarks/StreamBench.scala @@ -2,6 +2,9 @@ package benchmarks import java.util.concurrent.TimeUnit +import cats.data.Chain +import cats.instances.int._ +import cats.syntax.foldable._ import org.openjdk.jmh.annotations._ import scalaz.{IList, EphemeralStream} import scalaz.Scalaz._ @@ -21,10 +24,12 @@ class StreamBench { var vec2: Vector[Int] = _ var arr1: Array[Int] = _ var arr2: Array[Int] = _ - var str1: Stream[Int] = _ - var str2: Stream[Int] = _ + var str1: LazyList[Int] = _ + var str2: LazyList[Int] = _ var estr1: EphemeralStream[Int] = _ var estr2: EphemeralStream[Int] = _ + var chain1: Chain[Int] = _ + var chain2: Chain[Int] = _ @Setup def setup: Unit = { @@ -36,20 +41,21 @@ class StreamBench { vec2 = Vector.range(10000, 1, -1) arr1 = Array.range(1, 10000) arr2 = Array.range(10000, 1, -1) - str1 = Stream.range(1, 10000) - str2 = Stream.range(10000, 1, -1) + str1 = LazyList.range(1, 10000) + str2 = LazyList.range(10000, 1, -1) estr1 = EphemeralStream.range(1, 10000) - estr2 = EphemeralStream.fromStream(str2) + chain1 = Chain.fromSeq(list1) + chain2 = Chain.fromSeq(list2) } @Benchmark - def streamMax: Int = str1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).max + def lazylistMax: Int = str1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).max @Benchmark - def streamHead: Int = str1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).head + def lazylistHead: Int = str1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).head @Benchmark - def streamReverse: Int = str1.reverse.head + def lazylistReverse: Int = str1.reverse.head @Benchmark - def streamSort: Int = str2.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).sorted.head + def lazylistSort: Int = str2.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).sorted.head @Benchmark def ephemeralStreamMax: Option[Int] = estr1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).maximum @@ -99,4 +105,9 @@ class StreamBench { @Benchmark def arraySort: Int = arr2.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).sorted.head + def chainMax: Option[Int] = chain1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).maximumOption + @Benchmark + def chainHead: Option[Int] = chain1.map(_ + 1).filter(_ % 2 == 0).map(_ * 2).headOption + @Benchmark + def chainReverse: Option[Int] = chain1.reverse.headOption } diff --git a/src/main/scala/benchmarks/VectorBench.scala b/src/main/scala/benchmarks/VectorBench.scala index a97ed11..a56f297 100644 --- a/src/main/scala/benchmarks/VectorBench.scala +++ b/src/main/scala/benchmarks/VectorBench.scala @@ -6,6 +6,7 @@ import scala.annotation.tailrec import scala.collection.immutable.VectorBuilder import scala.collection.mutable.{ArrayBuilder, ListBuffer} +import cats.data.Chain import org.openjdk.jmh.annotations._ import scalaz.{IList, ICons, INil} @@ -107,6 +108,17 @@ class VectorBench { b.result } + def chain(n: Int): Chain[Int] = { + + @tailrec def work(acc: Chain[Int], m: Int): Chain[Int] = m match { + case _ if m == n => acc + case _ => work(m +: acc, m + 1) + } + + work(Chain.empty, 0) + + } + def foryield(n: Int): IndexedSeq[Int] = for (i <- 0 to n) yield i @Benchmark @@ -158,11 +170,17 @@ class VectorBench { @Benchmark def buffer100000: List[Int] = buffer(100000) + @Benchmark + def chain1000: Chain[Int] = chain(1000) + @Benchmark + def chain10000: Chain[Int] = chain(10000) + @Benchmark + def chain100000: Chain[Int] = chain(100000) + @Benchmark def foryield1000: IndexedSeq[Int] = foryield(1000) @Benchmark def foryield10000: IndexedSeq[Int] = foryield(10000) @Benchmark def foryield100000: IndexedSeq[Int] = foryield(100000) - }