├── basic ├── project │ └── build.properties ├── version.sbt ├── src │ └── test │ │ └── scala │ │ └── org │ │ └── scalameter │ │ └── examples │ │ └── RangeBenchmark.scala └── build.sbt ├── jbench ├── project │ └── build.properties ├── version.sbt ├── build.sbt └── src │ └── bench │ ├── scala │ └── org │ │ └── scalameter │ │ └── examples │ │ └── BufferBenchmark.scala │ └── java │ └── org │ └── scalameter │ └── examples │ └── ListBenchmark.java ├── include-statements ├── project │ └── build.properties ├── version.sbt ├── build.sbt └── src │ └── bench │ └── scala │ └── org │ └── scalameter │ └── examples │ └── collection-benchmarks.scala ├── offline-regression-report ├── project │ └── build.properties ├── version.sbt ├── src │ └── bench │ │ └── scala │ │ └── org │ │ └── scalameter │ │ └── examples │ │ └── ListBenchmark.scala └── build.sbt ├── basic-with-separate-config ├── project │ └── build.properties ├── version.sbt ├── src │ └── bench │ │ └── scala │ │ └── org │ │ └── scalameter │ │ └── examples │ │ └── RangeBenchmark.scala └── build.sbt ├── invocation-count-measurers ├── project │ └── build.properties ├── version.sbt ├── src │ └── bench │ │ └── scala │ │ └── org │ │ └── scalameter │ │ └── examples │ │ ├── BoxingCountBenchmark.scala │ │ ├── SimpleAllocationsBenchmark.scala │ │ ├── RegexMethodInvocationCountBenchmark.scala │ │ ├── SimpleMethodInvocationCountBenchmark.scala │ │ ├── FullMethodInvocationCountBenchmark.scala │ │ └── DescendantsAllocationsBenchmark.scala └── build.sbt ├── project └── plugins.sbt ├── .gitignore ├── README.md └── .travis.yml /basic/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.8 2 | -------------------------------------------------------------------------------- /basic/version.sbt: -------------------------------------------------------------------------------- 1 | version in ThisBuild := "0.21-SNAPSHOT" -------------------------------------------------------------------------------- /jbench/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.8 2 | -------------------------------------------------------------------------------- /jbench/version.sbt: -------------------------------------------------------------------------------- 1 | version in ThisBuild := "0.21-SNAPSHOT" -------------------------------------------------------------------------------- /include-statements/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.8 2 | -------------------------------------------------------------------------------- /include-statements/version.sbt: -------------------------------------------------------------------------------- 1 | version in ThisBuild := "0.21-SNAPSHOT" -------------------------------------------------------------------------------- /offline-regression-report/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.8 2 | -------------------------------------------------------------------------------- /basic-with-separate-config/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.8 2 | -------------------------------------------------------------------------------- /basic-with-separate-config/version.sbt: -------------------------------------------------------------------------------- 1 | version in ThisBuild := "0.21-SNAPSHOT" -------------------------------------------------------------------------------- /invocation-count-measurers/project/build.properties: -------------------------------------------------------------------------------- 1 | sbt.version=0.13.8 2 | -------------------------------------------------------------------------------- /invocation-count-measurers/version.sbt: -------------------------------------------------------------------------------- 1 | version in ThisBuild := "0.21-SNAPSHOT" -------------------------------------------------------------------------------- /offline-regression-report/version.sbt: -------------------------------------------------------------------------------- 1 | version in ThisBuild := "0.21-SNAPSHOT" -------------------------------------------------------------------------------- /project/plugins.sbt: -------------------------------------------------------------------------------- 1 | 2 | addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0") 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | target 4 | project/target 5 | tmp* 6 | 7 | 8 | *.*~ 9 | .history 10 | 11 | .classpath 12 | .project 13 | .settings 14 | .gitattributes 15 | 16 | .metadata/ 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # scalameter-examples 2 | 3 | Self-contained simple example projects that use specific ScalaMeter features. 4 | 5 | [![Build Status](https://travis-ci.org/scalameter/scalameter-examples.svg?branch=master)](https://travis-ci.org/scalameter/scalameter-examples) 6 | -------------------------------------------------------------------------------- /basic/src/test/scala/org/scalameter/examples/RangeBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | import org.scalameter.api._ 4 | 5 | object RangeBenchmark extends Bench.LocalTime { 6 | val sizes = Gen.range("size")(300000, 1500000, 300000) 7 | 8 | val ranges = for { 9 | size <- sizes 10 | } yield 0 until size 11 | 12 | performance of "Range" in { 13 | measure method "map" in { 14 | using(ranges) in { 15 | r => r.map(_ + 1) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /basic-with-separate-config/src/bench/scala/org/scalameter/examples/RangeBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | import org.scalameter.api._ 4 | 5 | object RangeBenchmark extends Bench.LocalTime { 6 | val sizes = Gen.range("size")(300000, 1500000, 300000) 7 | 8 | val ranges = for { 9 | size <- sizes 10 | } yield 0 until size 11 | 12 | performance of "Range" in { 13 | measure method "map" in { 14 | using(ranges) in { 15 | r => r.map(_ + 1) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: scala 2 | scala: 3 | - "2.10.4" 4 | - "2.11.1" 5 | jdk: 6 | - oraclejdk8 7 | env: 8 | - TEST_DIR=basic 9 | TASKS="test:test" 10 | - TEST_DIR=basic-with-separate-config 11 | TASKS="bench:test" 12 | - TEST_DIR=offline-regression-report 13 | TASKS="bench:test" 14 | - TEST_DIR=invocation-count-measurers 15 | TASKS="bench:test" 16 | - TEST_DIR=jbench 17 | TASKS="bench:test" 18 | script: cd $TEST_DIR && sbt $TRAVIS_SCALA_VERSION_ARG $TASKS 19 | branches: 20 | only: 21 | - master 22 | 23 | -------------------------------------------------------------------------------- /offline-regression-report/src/bench/scala/org/scalameter/examples/ListBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | import org.scalameter.api._ 4 | import org.scalameter.Measurer._ 5 | 6 | 7 | object ListBenchmark extends Bench.OfflineRegressionReport { 8 | val tupledLists = for { 9 | a <- Gen.range("a")(0, 100, 20) 10 | b <- Gen.range("b")(100, 200, 20) 11 | } yield ((0 until a).toList, (100 until b).toList) 12 | 13 | performance of "List" in { 14 | measure method "zip" in { 15 | using(tupledLists) config ( 16 | exec.benchRuns -> 10, // we want 10 benchmark runs 17 | exec.independentSamples -> 1 // and one JVM instance 18 | ) in { 19 | case (a, b) => a.zip(b) 20 | } 21 | } 22 | } 23 | 24 | override def measurer: Measurer[Double] = new MemoryFootprint 25 | 26 | // GZIPJSONSerializationPersistor is default but we want to choose custom path for regression data 27 | override def persistor: Persistor = new GZIPJSONSerializationPersistor("target/results") 28 | } 29 | -------------------------------------------------------------------------------- /invocation-count-measurers/src/bench/scala/org/scalameter/examples/BoxingCountBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | 4 | 5 | import org.scalameter.api._ 6 | import org.scalameter.picklers.noPickler._ 7 | 8 | 9 | 10 | class BoxingCountBenchmark extends Bench.Forked[Long] { 11 | val sizes = Gen.range("size")(300000, 1500000, 300000) 12 | 13 | val lists = for { 14 | size <- sizes 15 | } yield (0 until size).toList 16 | 17 | performance of "Range" in { 18 | measure method "map" in { 19 | using(lists) in { 20 | r => r.map(_ + 1) 21 | } 22 | } 23 | } 24 | 25 | // we want to count (auto)boxing of int values, so we just expect one map entry 26 | // and we reduce result map to `Long` to simplify benchmark 27 | def measurer: Measurer[Long] = Measurer.BoxingCount(classOf[Int]).map(v => 28 | v.copy(value = v.value.valuesIterator.sum) 29 | ) 30 | 31 | def aggregator: Aggregator[Long] = Aggregator.median 32 | 33 | // we want one JVM instance since this measurer is deterministic 34 | override def defaultConfig: Context = Context(exec.independentSamples -> 1) 35 | } 36 | -------------------------------------------------------------------------------- /basic/build.sbt: -------------------------------------------------------------------------------- 1 | /** This is the simplest possible use of ScalaMeter. 2 | * It allows running ScalaMeter benchmarks as part of the test suite. 3 | * It means, that when the test command is run, ScalaMeter benchmarks are run along 4 | * the tests from other test frameworks, such as ScalaTest or ScalaCheck. 5 | */ 6 | lazy val basic = Project( 7 | "basic", 8 | file("."), 9 | settings = Defaults.coreDefaultSettings ++ Seq( 10 | name := "scalameter-examples", 11 | organization := "com.storm-enroute", 12 | scalaVersion := "2.11.1", 13 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-Xlint"), 14 | publishArtifact := false, 15 | libraryDependencies ++= Seq( 16 | "com.storm-enroute" %% "scalameter" % version.value % "test" // ScalaMeter version is set in version.sbt 17 | ), 18 | resolvers ++= Seq( 19 | "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", 20 | "Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases" 21 | ), 22 | testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), 23 | parallelExecution in Test := false, 24 | logBuffered := false 25 | ) 26 | ) 27 | -------------------------------------------------------------------------------- /invocation-count-measurers/build.sbt: -------------------------------------------------------------------------------- 1 | lazy val Benchmark = config("bench") extend Test 2 | 3 | /** This allows running ScalaMeter benchmarks in separate sbt configuration. 4 | * It means, that when you want run your benchmarks you should type `bench:test` in sbt console. 5 | */ 6 | lazy val invocationCountMeasurers = Project( 7 | "invocation-count-measurers", 8 | file("."), 9 | settings = Defaults.coreDefaultSettings ++ Seq( 10 | name := "scalameter-examples", 11 | organization := "com.storm-enroute", 12 | scalaVersion := "2.11.4", 13 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-Xlint"), 14 | publishArtifact := false, 15 | libraryDependencies ++= Seq( 16 | "com.storm-enroute" %% "scalameter" % version.value % "bench" // ScalaMeter version is set in version.sbt 17 | ), 18 | resolvers ++= Seq( 19 | Opts.resolver.sonatypeReleases, 20 | Opts.resolver.sonatypeSnapshots 21 | ), 22 | testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), 23 | parallelExecution in Benchmark := false, 24 | logBuffered := false 25 | ) 26 | ) configs ( 27 | Benchmark 28 | ) settings( 29 | inConfig(Benchmark)(Defaults.testSettings): _* 30 | ) 31 | -------------------------------------------------------------------------------- /offline-regression-report/build.sbt: -------------------------------------------------------------------------------- 1 | lazy val Benchmark = config("bench") extend Test 2 | 3 | /** This allows running ScalaMeter benchmarks in separate sbt configuration. 4 | * It means, that when you want run your benchmarks you should type `bench:test` in sbt console. 5 | */ 6 | lazy val offlineRegressionReport = Project( 7 | "offline-regression-report", 8 | file("."), 9 | settings = Defaults.coreDefaultSettings ++ Seq( 10 | name := "scalameter-examples", 11 | organization := "com.storm-enroute", 12 | scalaVersion := "2.11.4", 13 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-Xlint"), 14 | publishArtifact := false, 15 | libraryDependencies ++= Seq( 16 | "com.storm-enroute" %% "scalameter" % version.value % "bench" // ScalaMeter version is set in version.sbt 17 | ), 18 | resolvers ++= Seq( 19 | Opts.resolver.sonatypeReleases, 20 | Opts.resolver.sonatypeSnapshots 21 | ), 22 | testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), 23 | parallelExecution in Benchmark := false, 24 | logBuffered := false 25 | ) 26 | ) configs ( 27 | Benchmark 28 | ) settings( 29 | inConfig(Benchmark)(Defaults.testSettings): _* 30 | ) 31 | -------------------------------------------------------------------------------- /jbench/build.sbt: -------------------------------------------------------------------------------- 1 | lazy val Benchmark = config("bench") extend Test 2 | 3 | /** This allows running ScalaMeter benchmarks in separate sbt configuration. 4 | * It means, that when you want run your benchmarks you should type `bench:test` in sbt console. 5 | */ 6 | lazy val jbench = Project( 7 | "jbench", 8 | file("."), 9 | settings = Defaults.coreDefaultSettings ++ Seq( 10 | name := "scalameter-examples", 11 | organization := "com.storm-enroute", 12 | scalaVersion := "2.11.1", 13 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-Xlint"), 14 | publishArtifact := false, 15 | libraryDependencies ++= Seq( 16 | "com.storm-enroute" %% "scalameter" % version.value % "bench" // ScalaMeter version is set in version.sbt 17 | ), 18 | resolvers ++= Seq( 19 | "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", 20 | "Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases" 21 | ), 22 | testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), 23 | parallelExecution in Benchmark := false, 24 | logBuffered := false 25 | ) 26 | ) configs( 27 | Benchmark 28 | ) settings( 29 | inConfig(Benchmark)(Defaults.testSettings): _* 30 | ) 31 | -------------------------------------------------------------------------------- /basic-with-separate-config/build.sbt: -------------------------------------------------------------------------------- 1 | lazy val Benchmark = config("bench") extend Test 2 | 3 | /** This allows running ScalaMeter benchmarks in separate sbt configuration. 4 | * It means, that when you want run your benchmarks you should type `bench:test` in sbt console. 5 | */ 6 | lazy val basic = Project( 7 | "basic-with-separate-config", 8 | file("."), 9 | settings = Defaults.coreDefaultSettings ++ Seq( 10 | name := "scalameter-examples", 11 | organization := "com.storm-enroute", 12 | scalaVersion := "2.11.1", 13 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-Xlint"), 14 | publishArtifact := false, 15 | libraryDependencies ++= Seq( 16 | "com.storm-enroute" %% "scalameter" % version.value % "bench" // ScalaMeter version is set in version.sbt 17 | ), 18 | resolvers ++= Seq( 19 | "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots", 20 | "Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases" 21 | ), 22 | testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), 23 | parallelExecution in Benchmark := false, 24 | logBuffered := false 25 | ) 26 | ) configs( 27 | Benchmark 28 | ) settings( 29 | inConfig(Benchmark)(Defaults.testSettings): _* 30 | ) 31 | -------------------------------------------------------------------------------- /include-statements/build.sbt: -------------------------------------------------------------------------------- 1 | lazy val Benchmark = config("bench") extend Test 2 | 3 | /** This allows running ScalaMeter benchmarks in separate sbt configuration. 4 | * It means, that when you want run your benchmarks you should type `bench:test` 5 | * in sbt console. 6 | */ 7 | lazy val includeStatements = Project( 8 | "include-statements", 9 | file("."), 10 | settings = Defaults.coreDefaultSettings ++ Seq( 11 | name := "scalameter-examples", 12 | organization := "com.storm-enroute", 13 | scalaVersion := "2.11.1", 14 | scalacOptions ++= Seq("-deprecation", "-unchecked", "-feature", "-Xlint"), 15 | publishArtifact := false, 16 | libraryDependencies ++= Seq( 17 | // ScalaMeter version is set in version.sbt 18 | "com.storm-enroute" %% "scalameter" % version.value % "bench" 19 | ), 20 | resolvers ++= Seq( 21 | "Sonatype OSS Snapshots" at 22 | "https://oss.sonatype.org/content/repositories/snapshots", 23 | "Sonatype OSS Releases" at 24 | "https://oss.sonatype.org/content/repositories/releases" 25 | ), 26 | testFrameworks += new TestFramework("org.scalameter.ScalaMeterFramework"), 27 | parallelExecution in Benchmark := false, 28 | logBuffered := false 29 | ) 30 | ) configs( 31 | Benchmark 32 | ) settings( 33 | inConfig(Benchmark)(Defaults.testSettings): _* 34 | ) 35 | -------------------------------------------------------------------------------- /invocation-count-measurers/src/bench/scala/org/scalameter/examples/SimpleAllocationsBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | 4 | 5 | import org.scalameter.api._ 6 | import org.scalameter.execution.invocation.InvocationCountMatcher 7 | import org.scalameter.picklers.noPickler._ 8 | import scala.util.Random 9 | 10 | 11 | 12 | class SimpleAllocationsBenchmark extends Bench.Forked[Long] { 13 | val sizes = Gen.range("size")(300000, 1500000, 300000) 14 | 15 | val lists = for { 16 | size <- sizes 17 | } yield (0 until size).toList 18 | 19 | performance of "List" in { 20 | measure method "map" in { 21 | using(lists) in { 22 | // approximately half of elements should be counted 23 | l => l.map(e => if (Random.nextBoolean()) Left(e) else Right(e)) 24 | } 25 | } 26 | } 27 | 28 | // we want to count allocations of `Right`, so we just expect one map entry 29 | // and we reduce result map to `Long` to simplify benchmark 30 | def measurer: Measurer[Long] = Measurer.MethodInvocationCount( 31 | InvocationCountMatcher.allocations(classOf[Right[_, _]]) 32 | ).map(v => v.copy(value = v.value.valuesIterator.sum)) 33 | 34 | def aggregator: Aggregator[Long] = Aggregator.median 35 | 36 | // we want one JVM instance since this measurer is deterministic 37 | override def defaultConfig: Context = Context(exec.independentSamples -> 1) 38 | } 39 | -------------------------------------------------------------------------------- /invocation-count-measurers/src/bench/scala/org/scalameter/examples/RegexMethodInvocationCountBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | import org.scalameter.api._ 4 | import org.scalameter.api.Aggregator.Implicits._ 5 | import org.scalameter.execution.invocation.InvocationCountMatcher 6 | import org.scalameter.picklers.noPickler._ 7 | 8 | 9 | class RegexMethodInvocationCountBenchmark extends Bench.Forked[Map[String, Long]] { 10 | val sizes = Gen.range("size")(1000, 10000, 1000) 11 | val methods = Gen.enumeration("method")( 12 | (bi: BigInt) => bi.toString(), (bi: BigInt) => bi.toString(10), (bi: BigInt) => bi.toByteArray 13 | ) 14 | 15 | val ranges = for { 16 | size <- sizes 17 | } yield 0 until size 18 | 19 | val combined = Gen.crossProduct(ranges, methods) 20 | 21 | performance of "Range" in { 22 | measure method "foreach" in { 23 | using(combined) in { 24 | // count should equal range size for all methods 25 | case (r, m) => r.foreach(e => m(BigInt(e))) 26 | } 27 | } 28 | } 29 | 30 | // we want to count all methods that begins with "to" 31 | def measurer: Measurer[Map[String, Long]] = Measurer.MethodInvocationCount( 32 | InvocationCountMatcher.forRegex("scala.math.BigInt".r, "^to\\w+".r) 33 | ) 34 | 35 | def aggregator: Aggregator[Map[String, Long]] = Aggregator.median 36 | 37 | // we want one JVM instance since this measurer is deterministic 38 | override def defaultConfig: Context = Context(exec.independentSamples -> 1) 39 | } 40 | -------------------------------------------------------------------------------- /invocation-count-measurers/src/bench/scala/org/scalameter/examples/SimpleMethodInvocationCountBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | import org.scalameter.api._ 4 | import org.scalameter.execution.invocation.InvocationCountMatcher 5 | import org.scalameter.picklers.noPickler._ 6 | 7 | 8 | class SimpleMethodInvocationCountBenchmark extends Bench.Forked[Long] { 9 | val sizes = Gen.range("size")(1000, 10000, 1000) 10 | val methods = Gen.enumeration("method")( 11 | (bi: BigInt) => bi.toString(), (bi: BigInt) => bi.toString(10), (bi: BigInt) => bi.toByteArray 12 | ) 13 | 14 | val ranges = for { 15 | size <- sizes 16 | } yield 0 until size 17 | 18 | val combined = Gen.crossProduct(ranges, methods) 19 | 20 | performance of "Range" in { 21 | measure method "foreach" in { 22 | using(combined) in { 23 | // count should equal range size for both toString methods, and 0 for toByteArray method 24 | case (r, m) => r.foreach(e => m(BigInt(e))) 25 | } 26 | } 27 | } 28 | 29 | // we want to count invocations of `BigInt.toString`, so we just expect one map entry 30 | // and we reduce result map to `Long` to simplify benchmark 31 | def measurer: Measurer[Long] = Measurer.MethodInvocationCount( 32 | InvocationCountMatcher.forName("scala.math.BigInt", "toString") 33 | ).map(v => v.copy(value = v.value.valuesIterator.sum)) 34 | 35 | def aggregator: Aggregator[Long] = Aggregator.median 36 | 37 | // we want one JVM instance since this measurer is deterministic 38 | override def defaultConfig: Context = Context(exec.independentSamples -> 1) 39 | } 40 | -------------------------------------------------------------------------------- /invocation-count-measurers/src/bench/scala/org/scalameter/examples/FullMethodInvocationCountBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | import org.scalameter.api._ 4 | import org.scalameter.execution.invocation.InvocationCountMatcher 5 | import org.scalameter.picklers.noPickler._ 6 | 7 | 8 | class FullMethodInvocationCountBenchmark extends Bench.Forked[Long] { 9 | val sizes = Gen.range("size")(1000, 10000, 1000) 10 | val methods = Gen.enumeration("method")( 11 | (bi: BigInt) => bi.toString(), (bi: BigInt) => bi.toString(10), (bi: BigInt) => bi.toByteArray 12 | ) 13 | 14 | val ranges = for { 15 | size <- sizes 16 | } yield 0 until size 17 | 18 | val combined = Gen.crossProduct(ranges, methods) 19 | 20 | performance of "Range" in { 21 | measure method "foreach" in { 22 | using(combined) in { 23 | // count should equal range size for no-arg toString method, and 0 for rest methods 24 | case (r, m) => r.foreach(e => m(BigInt(e))) 25 | } 26 | } 27 | } 28 | 29 | // we want to count only no-arg toString method, so we just expect one map entry 30 | // and we reduce result map to `Long` to simplify benchmark 31 | def measurer: Measurer[Long] = Measurer.MethodInvocationCount( 32 | InvocationCountMatcher.forClass(classOf[BigInt], classOf[BigInt].getMethod("toString")) 33 | ).map(v => v.copy(value = v.value.valuesIterator.sum)) 34 | 35 | def aggregator: Aggregator[Long] = Aggregator.median 36 | 37 | // we want one JVM instance since this measurer is deterministic 38 | override def defaultConfig: Context = Context(exec.independentSamples -> 1) 39 | } 40 | -------------------------------------------------------------------------------- /invocation-count-measurers/src/bench/scala/org/scalameter/examples/DescendantsAllocationsBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | 4 | 5 | import org.scalameter.api._ 6 | import org.scalameter.api.Aggregator.Implicits._ 7 | import org.scalameter.execution.invocation.InvocationCountMatcher 8 | import org.scalameter.execution.invocation.InvocationCountMatcher.MethodMatcher 9 | import org.scalameter.execution.invocation.InvocationCountMatcher.ClassMatcher 10 | import org.scalameter.picklers.noPickler._ 11 | import scala.util.Random 12 | 13 | 14 | 15 | class DescendantsAllocationsBenchmark extends Bench.Forked[Map[String, Long]] { 16 | val sizes = Gen.range("size")(300000, 1500000, 300000) 17 | 18 | val lists = for { 19 | size <- sizes 20 | } yield (0 until size).toList 21 | 22 | performance of "List" in { 23 | measure method "map" in { 24 | using(lists) in { 25 | // since we count both Left and Right, all list elements should be counted 26 | l => l.map(e => if (Random.nextBoolean()) Left(e) else Right(e)) 27 | } 28 | } 29 | } 30 | 31 | // we want to count allocations of `Either` 32 | def measurer: Measurer[Map[String, Long]] = Measurer.MethodInvocationCount( 33 | InvocationCountMatcher( 34 | ClassMatcher.Descendants(classOf[Either[_, _]], direct = true, withSelf = false), 35 | MethodMatcher.Allocation 36 | ) 37 | ) 38 | 39 | def aggregator: Aggregator[Map[String, Long]] = Aggregator.median 40 | 41 | // we want one JVM instance since this measurer is deterministic 42 | override def defaultConfig: Context = Context(exec.independentSamples -> 1) 43 | } 44 | -------------------------------------------------------------------------------- /include-statements/src/bench/scala/org/scalameter/examples/collection-benchmarks.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | 4 | 5 | import org.scalameter.api._ 6 | 7 | 8 | 9 | /** When a benchmark is implemented as a trait, 10 | * it is actually a *bench template*. 11 | * Bench templates are not automatically detected as tests by SBT. 12 | * Instead, they have to be included into bench groups with the 13 | * include statement. 14 | */ 15 | trait RangeBenchmark extends Bench.OfflineReport { 16 | val sizes = Gen.range("size")(300000, 1500000, 300000) 17 | 18 | val ranges = for { 19 | size <- sizes 20 | } yield 0 until size 21 | 22 | performance of "Range" in { 23 | measure method "map" in { 24 | using(ranges) in { 25 | r => r.map(_ + 1) 26 | } 27 | } 28 | } 29 | } 30 | 31 | 32 | /** Another benchmark template, this time used to measure the memory footprint. 33 | */ 34 | trait RangeMemoryFootprint extends Bench.OfflineReport { 35 | override def measurer = new Measurer.MemoryFootprint 36 | 37 | val sizes = Gen.range("size")(1000000, 5000000, 2000000) 38 | 39 | performance of "MemoryFootprint" in { 40 | performance of "Array" in { 41 | using(sizes) config ( 42 | exec.minWarmupRuns -> 2, 43 | exec.maxWarmupRuns -> 5, 44 | exec.benchRuns -> 5, 45 | exec.independentSamples -> 1 46 | ) in { sz => 47 | // The memory footprint of the resulting array gets measured. 48 | (0 until sz).toArray 49 | } 50 | } 51 | } 52 | } 53 | 54 | 55 | object CollectionBenchmarks extends Bench.Group { 56 | // We override the resultDir key here to ensure that the reports 57 | // get generated in different subdirectories. 58 | performance of "memory" config( 59 | reports.resultDir -> "target/benchmarks/memory" 60 | ) in { 61 | include(new RangeMemoryFootprint {}) 62 | } 63 | 64 | // Same here -- related report is separate from memory footprint report. 65 | performance of "running time" config( 66 | reports.resultDir -> "target/benchmarks/time" 67 | ) in { 68 | include(new RangeBenchmark {}) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /jbench/src/bench/scala/org/scalameter/examples/BufferBenchmark.scala: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples 2 | 3 | 4 | 5 | import org.scalameter.{Context, Gen} 6 | import org.scalameter.api._ 7 | import org.scalameter.japi.JBench 8 | import scala.collection.mutable 9 | import scala.util.Random 10 | 11 | 12 | 13 | class BufferBenchmark extends JBench.OfflineReport { 14 | // we don't need `JGen` here, we can take advantage of the Scala API 15 | val sizes = Gen.exponential("size")(100, 10000, 10) 16 | 17 | // we don't need `JGen` here, 18 | // we can take advantage of the Scala API and for comprehensions 19 | val arrayBuffers = for { 20 | size <- sizes 21 | } yield (size, new mutable.ArrayBuffer[Int]()) 22 | 23 | // we don't need `JGen` here, 24 | // we can take advantage of the Scala API and for comprehensions 25 | val listBuffers = for { 26 | size <- sizes 27 | } yield (size, new mutable.ListBuffer[Int]()) 28 | 29 | // we don't need `ContextBuilder` here, we can take advantage of Scala API 30 | override def defaultConfig: Context = Context( 31 | exec.benchRuns -> 25, 32 | exec.independentSamples -> 2 33 | ) 34 | 35 | def arrayBufferSetup(v: (Int, mutable.ArrayBuffer[Int])): Unit = { 36 | val (size, buffer) = v 37 | 38 | val random: Random = new Random(size) 39 | (0 to size).foreach(_ => buffer += random.nextInt()) 40 | } 41 | 42 | def listBufferSetup(v: (Int, mutable.ListBuffer[Int])): Unit = { 43 | val (size, buffer) = v 44 | 45 | val random: Random = new Random(size) 46 | (0 to size).foreach(i => buffer += random.nextInt()) 47 | } 48 | 49 | @gen("arrayBuffers") 50 | @setup("arrayBufferSetup") 51 | @benchmark("buffers.forloops") 52 | @curve("array") 53 | def arrayBufferSum(v: (Int, mutable.ArrayBuffer[Int])): Int = { 54 | val (_, buffer) = v 55 | 56 | buffer.sum 57 | } 58 | 59 | @gen("listBuffers") 60 | @setup("listBufferSetup") 61 | @benchmark("buffers.forloops") 62 | @curve("list") 63 | def listBufferSum(v: (Int, mutable.ListBuffer[Int])): Int = { 64 | val (_, buffer) = v 65 | 66 | buffer.sum 67 | } 68 | 69 | @gen("arrayBuffers") 70 | @benchmark("buffers.ops.add") 71 | @curve("array") 72 | def arrayBufferAdd(v: (Int, mutable.ArrayBuffer[Int])) = { 73 | val (size, buffer) = v 74 | 75 | val random = new Random(size) 76 | var i = 0 77 | while (i < size) { 78 | buffer += random.nextInt() 79 | i += 1 80 | } 81 | 82 | buffer 83 | } 84 | 85 | @gen("listBuffers") 86 | @benchmark("buffers.ops.add") 87 | @curve("list") 88 | def listBufferAdd(v: (Int, mutable.ListBuffer[Int])) = { 89 | val (size, buffer) = v 90 | 91 | val random = new Random(size) 92 | var i = 0 93 | while (i < size) { 94 | buffer += random.nextInt() 95 | i += 1 96 | } 97 | 98 | buffer 99 | } 100 | 101 | @gen("arrayBuffers") 102 | @setup("arrayBufferSetup") 103 | @benchmark("buffers.ops.remove") 104 | @curve("array") 105 | def arrayBufferRemove(v: (Int, mutable.ArrayBuffer[Int])) = { 106 | val (size, buffer) = v 107 | 108 | var random = new Random(size) 109 | val newBuffer = random.shuffle(buffer) 110 | random = new Random(size) 111 | var i = 0 112 | while (i < size) { 113 | newBuffer -= random.nextInt() 114 | i += 1 115 | } 116 | 117 | buffer 118 | } 119 | 120 | @gen("listBuffers") 121 | @setup("listBufferSetup") 122 | @benchmark("buffers.ops.remove") 123 | @curve("list") 124 | def listBufferRemove(v: (Int, mutable.ListBuffer[Int])) = { 125 | val (size, buffer) = v 126 | 127 | var random = new Random(size) 128 | val newBuffer = random.shuffle(buffer) 129 | random = new Random(size) 130 | var i = 0 131 | while (i < size) { 132 | newBuffer -= random.nextInt() 133 | i += 1 134 | } 135 | 136 | buffer 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /jbench/src/bench/java/org/scalameter/examples/ListBenchmark.java: -------------------------------------------------------------------------------- 1 | package org.scalameter.examples; 2 | 3 | import java.util.*; 4 | import org.scalameter.Context; 5 | import org.scalameter.japi.ContextBuilder; 6 | import org.scalameter.japi.Fun1; 7 | import org.scalameter.japi.JBench; 8 | import org.scalameter.japi.JGen; 9 | import org.scalameter.japi.annotation.*; 10 | import scala.Tuple2; 11 | 12 | 13 | public class ListBenchmark extends JBench.OfflineReport { 14 | public final JGen sizes = JGen.exponential("size", 100, 10000, 10); 15 | 16 | // on java 8 `map` combinator can be expressed using lambdas 17 | public final JGen>> arrayLists = sizes.zip( 18 | sizes.map(new Fun1>() { 19 | public ArrayList apply(Integer v) { 20 | return new ArrayList(); 21 | } 22 | }) 23 | ); 24 | 25 | // on java 8 `map` combinator can be expressed using lambdas 26 | public final JGen>> linkedLists = sizes.zip( 27 | sizes.map(new Fun1>() { 28 | public LinkedList apply(Integer v) { 29 | return new LinkedList(); 30 | } 31 | }) 32 | ); 33 | 34 | @Override 35 | public Context defaultConfig() { 36 | return new ContextBuilder() 37 | .put("exec.benchRuns", 25) 38 | .put("exec.independentSamples", 2) 39 | .build(); 40 | } 41 | 42 | public void arrayListSetup(Tuple2> v) { 43 | int size = v._1(); 44 | ArrayList list = v._2(); 45 | 46 | Random random = new Random(size); 47 | for (int i = 0; i < size; i++) { 48 | list.add(random.nextInt()); 49 | } 50 | } 51 | 52 | public void linkedListSetup(Tuple2> v) { 53 | int size = v._1(); 54 | LinkedList list = v._2(); 55 | 56 | Random random = new Random(size); 57 | for (int i = 0; i < size; i++) { 58 | list.add(random.nextInt()); 59 | } 60 | } 61 | 62 | @gen("arrayLists") 63 | @setup("arrayListSetup") 64 | @benchmark("lists.forloops") 65 | @curve("array") 66 | public int arrayListSum(Tuple2> v) { 67 | ArrayList list = v._2(); 68 | int result = 0; 69 | 70 | for (Integer elem : list) { 71 | result += elem; 72 | 73 | } 74 | return result; 75 | } 76 | 77 | @gen("linkedLists") 78 | @setup("linkedListSetup") 79 | @benchmark("lists.forloops") 80 | @curve("linked") 81 | public int linkedListSum(Tuple2> v) { 82 | LinkedList list = v._2(); 83 | int result = 0; 84 | 85 | for (Integer elem : list) { 86 | result += elem; 87 | 88 | } 89 | return result; 90 | } 91 | 92 | @gen("arrayLists") 93 | @benchmark("lists.ops.add") 94 | @curve("array") 95 | public ArrayList arrayListAdd(Tuple2> v) { 96 | int size = v._1(); 97 | ArrayList list = v._2(); 98 | 99 | Random random = new Random(size); 100 | for (int i = 0; i < size; i++) { 101 | list.add(random.nextInt()); 102 | } 103 | 104 | return list; 105 | } 106 | 107 | @gen("linkedLists") 108 | @benchmark("lists.ops.add") 109 | @curve("linked") 110 | public LinkedList linkedListAdd(Tuple2> v) { 111 | int size = v._1(); 112 | LinkedList list = v._2(); 113 | 114 | Random random = new Random(size); 115 | for (int i = 0; i < size; i++) { 116 | list.add(random.nextInt()); 117 | } 118 | 119 | return list; 120 | } 121 | 122 | @gen("arrayLists") 123 | @setup("arrayListSetup") 124 | @benchmark("lists.ops.remove") 125 | @curve("array") 126 | public ArrayList arrayListRemove(Tuple2> v) { 127 | int size = v._1(); 128 | ArrayList list = v._2(); 129 | 130 | Random random = new Random(size); 131 | Collections.shuffle(list, random); 132 | random = new Random(size); 133 | for (int i = 0; i < size; i++) { 134 | list.remove((Integer) random.nextInt()); 135 | } 136 | 137 | return list; 138 | } 139 | 140 | @gen("linkedLists") 141 | @setup("linkedListSetup") 142 | @benchmark("lists.ops.remove") 143 | @curve("linked") 144 | public LinkedList linkedListRemove(Tuple2> v) { 145 | int size = v._1(); 146 | LinkedList list = v._2(); 147 | 148 | Random random = new Random(size); 149 | Collections.shuffle(list, random); 150 | random = new Random(size); 151 | for (int i = 0; i < size; i++) { 152 | list.remove((Integer) random.nextInt()); 153 | } 154 | 155 | return list; 156 | } 157 | } 158 | --------------------------------------------------------------------------------