com.sksamuel.scam.ScamDsl.scala Maven / Gradle / Ivy
package com.sksamuel.scam
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Await, Future}
/** @author Stephen Samuel */
trait ScamDsl {
def measure[T](thunk: => T): (T, MeasurementResult) = {
val stopwatch = new Stopwatch
stopwatch.start()
val t = thunk
stopwatch.stop()
val elapsed = stopwatch.elapsed
(t, MeasurementResult(elapsed))
}
def benchmark(iterations: Int)(thunk: => Any): BenchmarkResult = benchmark(0, iterations)(thunk)
def benchmark(warmUps: Int, iterations: Int)(thunk: => Any): BenchmarkResult = {
repeat(warmUps)(thunk)
val stopwatch = new Stopwatch
stopwatch.start()
repeat(iterations)(thunk)
stopwatch.stop()
val elapsed = stopwatch.elapsed
BenchmarkResult(warmUps, iterations, elapsed)
}
def benchmarkFutures(iterations: Int)
(thunk: => Future[Any])
(implicit executionContext: ExecutionContext): BenchmarkResult = {
val stopwatch = new Stopwatch
stopwatch.start()
val futures = for ( k <- 1 to iterations ) yield thunk
val future = Future.sequence(futures)
Await.ready(future, Duration.Inf)
val elapsed = stopwatch.elapsed
BenchmarkResult(0, iterations, elapsed)
}
def repeat(n: Int)(thunk: => Any): Unit = {
for ( k <- 1 to n ) {
thunk
}
}
}
object Scam extends ScamDsl
case class MeasurementResult(duration: FiniteDuration) {
override def toString: String = {
val sb = new StringBuilder
sb append s"Total executed time: ${duration.toMillis} millis\n"
sb.mkString
}
}
case class BenchmarkResult(warmups: Int, iterations: Int, duration: FiniteDuration) {
override def toString: String = {
val avg = if (iterations == 0) 0 else duration.toMillis / iterations
val perSecond = {
if (duration.toMillis == 0) 0
else "%.2f" format iterations / duration.toMillis.toDouble * 1000
}
val sb = new StringBuilder
sb append s"$warmups warmup runs\n"
sb append s"$iterations benchmarked iterations\n"
sb append s"Total executed time: ${duration.toMillis} millis\n"
sb append s"Average time per iteration: $avg millis\n"
sb append s"$perSecond iterations per second\n"
sb.mkString
}
}