All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalameter.performance-test.scala Maven / Gradle / Ivy

The newest version!
package org.scalameter



import java.util.Date
import org.scalameter.picklers.Pickler
import org.scalameter.utils.Tree
import scala.language.existentials
import scala.collection._
import scala.reflect.ClassTag
import scala.util.DynamicVariable



/** Abstract required for the [[org.scalameter.ScalaMeterFramework]] to find all
 *  performance tests.
 */
sealed trait AbstractPerformanceTest {
  def executeTests(): Boolean
}


abstract class BasePerformanceTest[U] extends AbstractPerformanceTest {
  import BasePerformanceTest._

  setupzipper.value =
    Tree.Zipper.root[Setup[_]](measurer.prepareContext(currentContext ++ defaultConfig))

  protected case class Scope(name: String, context: Context) {
    def config(kvs: KeyValue*): Scope = config(context ++ Context(kvs: _*))
    def config(ctx: Context): Scope = Scope(name, context ++ ctx)
    def in(block: =>Unit): Unit = {
      val oldscope = context(Key.dsl.scope)
      descendInScope(name, context + (Key.dsl.scope -> (name :: oldscope))) {
        block
      }
    }
  }

  protected case class Using[T](benchmark: Setup[T]) {
    def beforeTests(block: =>Any) =
      Using(benchmark.copy(setupbeforeall = Some(() => block)))
    def setUp(block: T => Any) =
      Using(benchmark.copy(setup = Some(block)))
    def tearDown(block: T => Any) =
      Using(benchmark.copy(teardown = Some(block)))
    def afterTests(block: =>Any) =
      Using(benchmark.copy(teardownafterall = Some(() => block)))
    def warmUp(block: =>Any) =
      Using(benchmark.copy(customwarmup = Some(() => block)))
    def curve(name: String) =
      Using(benchmark.copy(context = benchmark.context + (Key.dsl.curve -> name)))
    def config(kvs: KeyValue*): Using[T] =
      config(Context(kvs: _*))
    def config(ctx: Context): Using[T] =
      Using(benchmark.copy(context = benchmark.context ++ ctx))
    def in(block: T => Any): Unit = {
      setupzipper.value = setupzipper.value.addItem(benchmark.copy(snippet = block))
    }
  }

  private def setupFilter(setup: Setup[_]): Boolean = {
    val sf = currentContext(Key.scopeFilter)
    val fullname = setup.context.scope + "." + setup.context.curve
    val regex = sf.r
    regex.findFirstIn(fullname) != None
  }

  type SameType

  def isModule = this.getClass.getSimpleName.endsWith("$")

  def defaultConfig: Context = Context.empty

  /** Allows rebuilding of setup zipper after test initialization.
   *
   *  Default implementation is empty.
   */
  def rebuildSetupZipper(): Unit = {}

  /** Runs all the tests in this test class or singleton object.
   */
  def executeTests(): Boolean = {
    rebuildSetupZipper()

    val datestart: Option[Date] = Some(new Date)
    val rawsetuptree = BasePerformanceTest.setupzipper.value.result
    val setuptree = rawsetuptree.filter(setupFilter)

    val resulttree = dyn.currentContext.withValue(setuptree.context) {
      measurer.beforeExecution(setuptree.context)
      val resulttree =
        executor.run(setuptree.asInstanceOf[Tree[Setup[SameType]]], reporter, persistor)
      measurer.afterExecution(setuptree.context)
      resulttree
    }

    val dateend: Option[Date] = Some(new Date)
    val datedtree = resulttree.copy(context = resulttree.context +
      (Key.reports.startDate -> datestart) + (Key.reports.endDate -> dateend))
    reporter.report(datedtree, persistor)
  }

  /** The optional executor assigned to a particular body of DSL code.
   */
  def executor: Executor[U]

  def measurer: Measurer[U]

  def reporter: Reporter[U]

  def persistor: Persistor
}


object BasePerformanceTest {

  private[scalameter] val setupzipper =
    new DynamicVariable(Tree.Zipper.root[Setup[_]](currentContext))

  private[scalameter] def descendInScope(name: String, context: Context)(body: =>Unit): Unit = {
    setupzipper.value = setupzipper.value.descend.setContext(context)
    body
    setupzipper.value = setupzipper.value.ascend
  }

  private[scalameter] val curveNameCount =
    new java.util.concurrent.atomic.AtomicInteger(0)

  private[scalameter] def freshCurveName(): String =
    "Test-" + curveNameCount.getAndIncrement()

}


trait GroupedPerformanceTest extends BasePerformanceTest[Nothing] {
  private[scalameter] val includes =
    mutable.Set[(BasePerformanceTest[_], Tree.Zipper[Setup[_]])]()

  def include[T <: BasePerformanceTest[_]: ClassTag](newBenchmark: =>T) = {
    val cls = implicitly[ClassTag[T]].runtimeClass
    if (cls.getSimpleName.endsWith("$")) {
      log.error(
        s"Can only use `include` with anonymous classes instantiated from traits -- " +
        s"please make ${cls.getName} a trait and " +
        s"call include(new ${cls.getSimpleName} {}).")
      events.emit(Event(
        cls.getName,
        s"Can only use `include` with anonymous classes instantiated from traits -- " +
        s"please make ${cls.getName} a trait and " +
        s"call include(new ${cls.getSimpleName} {}).",
        Events.Error, new Exception("Cannot use non-anonymous benchmark class.")))
    } else {
      val oldvalue = BasePerformanceTest.setupzipper.value
      for (_ <- dyn.currentContext.using(oldvalue.current.context)) {
        val bench = newBenchmark
        includes += ((bench, BasePerformanceTest.setupzipper.value))
      }
      BasePerformanceTest.setupzipper.value = oldvalue
    }
  }

  override def executeTests(): Boolean = {
    val results = for ((b, z) <- includes) yield {
      BasePerformanceTest.setupzipper.value = z
      b.executeTests()
    }
    results.forall(_ == true)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy