diff --git a/framian-benchmarks/src/benchmark/scala/framian/benchmark/ColumnZipMapBenchmark.scala b/framian-benchmarks/src/benchmark/scala/framian/benchmark/ColumnZipMapBenchmark.scala new file mode 100644 index 0000000..ee821a3 --- /dev/null +++ b/framian-benchmarks/src/benchmark/scala/framian/benchmark/ColumnZipMapBenchmark.scala @@ -0,0 +1,66 @@ +package framian.benchmark + +import java.util.concurrent.TimeUnit + +import scala.collection.immutable.BitSet +import scala.util.Random + +import org.openjdk.jmh.annotations.{ Benchmark, Scope, State } +import org.openjdk.jmh.annotations.{ BenchmarkMode, Mode, OutputTimeUnit } + +import framian.Column +import framian.column.Mask + +class DenseColumnZipMapBenchmark { + + @Benchmark + def zipMapArray(data: DenseZipMapData) = { + val xs = data.data0 + val ys = data.data1 + val len = spire.math.min(xs.length, ys.length) + val zs = new Array[Double](len) + var i = 0 + while (i < xs.length && i < ys.length) { + zs(i) = xs(i) * ys(i) + i += 1 + } + zs + } + + @Benchmark + def zipMappedMaskedArray(data: DenseZipMapData) = { + val xs = data.data0 + val ys = data.data1 + val len = spire.math.min(xs.length, ys.length) + val na = data.na0 | data.na1 + val nm = (data.nm0 | data.nm1).filter(i => i < len && !na(i)) + val zs = new Array[Double](len) + var i = 0 + while (i < xs.length && i < ys.length) { + if (!(na(i) || nm(i))) + zs(i) = xs(i) * ys(i) + i += 1 + } + zs + } + + @Benchmark + def squareColumn(data: DenseZipMapData) = + data.col0.zipMap(data.col1)(_ * _) +} + +@State(Scope.Benchmark) +class DenseZipMapData { + val size = 1000 + val rng = new Random(42) + + val data0: Array[Double] = Array.fill(size)(rng.nextDouble) + val na0: Mask = Data.mask(rng, size, 0.1) + val nm0: Mask = Data.mask(rng, size, 0.01) + val col0: Column[Double] = Column.dense(data0, na0, nm0) + + val data1: Array[Double] = Array.fill(size)(rng.nextDouble) + val na1: Mask = Data.mask(rng, size, 0.1) + val nm1: Mask = Data.mask(rng, size, 0.01) + val col1: Column[Double] = Column.dense(data1, na1, nm1) +} diff --git a/framian/src/main/scala/framian/Column.scala b/framian/src/main/scala/framian/Column.scala index 9867248..5bc95ed 100644 --- a/framian/src/main/scala/framian/Column.scala +++ b/framian/src/main/scala/framian/Column.scala @@ -182,6 +182,16 @@ sealed trait Column[+A] { // TODO: Can't specialize in 2.10, but can in 2.11. */ def zipMap[B, C](that: Column[B])(f: (A, B) => C): Column[C] + /** + * Zips values together into 2-tuples. This is equivalent to calling + * `left.zipMap(right)((_, _))`. + * + * @param that the column to zip this column with + * + * @see [[Column#zipMap]] + */ + def zip[B](that: Column[B]): Column[(B, C)] = zipMap(that)((_, _)) + override def toString: String = (0 to 5).map(apply(_).toString).mkString("Column(", ", ", ", ...)") } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 5e7aeea..01fa86b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -13,8 +13,6 @@ object Dependencies { // Test libraries val Specs2 = "2.4.2" val ScalaCheck = "1.11.6" - - val Jmh = "1.0" } // Compile diff --git a/project/plugins.sbt b/project/plugins.sbt index 2229ac4..51291ad 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -8,6 +8,6 @@ def customAddSbtPlugin(m: ModuleID) = Defaults.sbtPluginExtra(m, "0.13", "2.10") libraryDependencies ++= Seq( customAddSbtPlugin("de.johoop" % "jacoco4sbt" % "2.1.6"), customAddSbtPlugin("me.lessis" % "bintray-sbt" % "0.1.2"), - customAddSbtPlugin("net.tixxit" % "sbt-benchmark" % "0.1.0") + customAddSbtPlugin("net.tixxit" % "sbt-benchmark" % "0.1.1") )