From 9dd3b61620faefec451a3d936044949581433f91 Mon Sep 17 00:00:00 2001 From: LMnet Date: Wed, 1 May 2019 14:15:47 +0700 Subject: [PATCH] Benchmarks for collectFirst on Chain --- .../cats/bench/ChainCollectFirstBench.scala | 108 ++++++++++++++++++ core/src/main/scala/cats/data/Chain.scala | 15 ++- 2 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 bench/src/main/scala/cats/bench/ChainCollectFirstBench.scala diff --git a/bench/src/main/scala/cats/bench/ChainCollectFirstBench.scala b/bench/src/main/scala/cats/bench/ChainCollectFirstBench.scala new file mode 100644 index 0000000000..b718667a05 --- /dev/null +++ b/bench/src/main/scala/cats/bench/ChainCollectFirstBench.scala @@ -0,0 +1,108 @@ +package cats.bench + +import cats.Foldable +import cats.data.Chain +import org.openjdk.jmh.annotations.{Benchmark, Scope, State} + +@State(Scope.Thread) +class ChainCollectFirstBench { + + private val foldableChain = Foldable[Chain] + + private val small = Chain(1, 2, 3, 4, 5) + private val smallLast = 5 + + private val medium = (0 to 10) + .foldLeft(Chain.empty[Int])((acc, _) => acc ++ Chain.fromSeq(0 to 10)) + private val mediumLast = 10 * 10 + + private val large = (0 to 1000) + .foldLeft(Chain.empty[Int])((acc, _) => acc ++ Chain.fromSeq(0 to 1000)) + private val largeLast = 1000 * 1000 + + @Benchmark + def collectFirstSmallNew: Option[Int] = small.collectFirst { + case x if x == smallLast => x + } + + @Benchmark + def collectFirstSmallFoldable: Option[Int] = foldableChain.collectFirst(small) { + case x if x == smallLast => x + } + + @Benchmark + def collectFirstMediumNew: Option[Int] = medium.collectFirst { + case x if x == mediumLast => x + } + + @Benchmark + def collectFirstMediumFoldable: Option[Int] = foldableChain.collectFirst(medium) { + case x if x == mediumLast => x + } + + @Benchmark + def collectFirstLargeNew: Option[Int] = medium.collectFirst { + case x if x == largeLast => x + } + + @Benchmark + def collectFirstLargeFoldable: Option[Int] = foldableChain.collectFirst(medium) { + case x if x == largeLast => x + } + + + + @Benchmark + def collectFirstSomeSmallNew: Option[Int] = small.collectFirstSome { + case x if x == smallLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSome2SmallNew: Option[Int] = small.collectFirstSome2 { + case x if x == smallLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSomeSmallFoldable: Option[Int] = foldableChain.collectFirstSome(small) { + case x if x == smallLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSomeMediumNew: Option[Int] = medium.collectFirstSome { + case x if x == mediumLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSome2MediumNew: Option[Int] = medium.collectFirstSome2 { + case x if x == mediumLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSomeMediumFoldable: Option[Int] = foldableChain.collectFirstSome(medium) { + case x if x == mediumLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSomeLargeNew: Option[Int] = medium.collectFirstSome { + case x if x == largeLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSome2LargeNew: Option[Int] = medium.collectFirstSome2 { + case x if x == largeLast => Some(x) + case _ => None + } + + @Benchmark + def collectFirstSomeLargeFoldable: Option[Int] = foldableChain.collectFirstSome(medium) { + case x if x == largeLast => Some(x) + case _ => None + } +} diff --git a/core/src/main/scala/cats/data/Chain.scala b/core/src/main/scala/cats/data/Chain.scala index d15fd4e138..faff843952 100644 --- a/core/src/main/scala/cats/data/Chain.scala +++ b/core/src/main/scala/cats/data/Chain.scala @@ -169,6 +169,19 @@ sealed abstract class Chain[+A] { final def collectFirstSome[B](f: A => Option[B]): Option[B] = collectFirst(Function.unlift(f)) + final def collectFirstSome2[B](f: A => Option[B]): Option[B] = { + var result: Option[B] = None + foreachUntil { a => + val x = f(a) + if (x.isDefined) { + result = x + true + } else false + } + result + } + + /** * Remove elements not matching the predicate */ @@ -584,8 +597,6 @@ sealed abstract private[data] class ChainInstances extends ChainInstances1 { override def forall[A](fa: Chain[A])(p: A => Boolean): Boolean = fa.forall(p) override def find[A](fa: Chain[A])(f: A => Boolean): Option[A] = fa.find(f) override def size[A](fa: Chain[A]): Long = fa.length - override def collectFirst[A, B](fa: Chain[A])(pf: PartialFunction[A, B]): Option[B] = fa.collectFirst(pf) - override def collectFirstSome[A, B](fa: Chain[A])(f: A => Option[B]): Option[B] = fa.collectFirstSome(f) def coflatMap[A, B](fa: Chain[A])(f: Chain[A] => B): Chain[B] = { @tailrec def go(as: Chain[A], res: ListBuffer[B]): Chain[B] =