Skip to content

Commit

Permalink
Add vendor benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
knutwalker committed Apr 9, 2015
1 parent d590997 commit 58fe7cd
Show file tree
Hide file tree
Showing 12 changed files with 810 additions and 28 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@ project/plugins/project/
.scala_dependencies
.worksheet
benchmarks/jmh-result.scsv
benchmarks/finagle/jmh-result.scsv
benchmarks/scala-redis-nb/jmh-result.scsv
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Copyright 2014 – 2015 Paul Horn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.twitter.finagle.redis

import rx.redis.util._

import com.twitter.finagle.redis.protocol._
import com.twitter.finagle.redis.util.StringToChannelBuffer
import com.twitter.finagle.{ Redis RedisClient }
import com.twitter.util.{ Await, Future }
import org.openjdk.jmh.annotations._

import java.util.concurrent.TimeUnit

@Threads(value = 1)
@Fork(value = 1)
@Warmup(iterations = 3)
@Measurement(iterations = 5)
@BenchmarkMode(Array(Mode.Throughput))
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Benchmark)
class FinaglePingBench {

private[this] final var client: Client = _

@Setup(Level.Iteration)
def prepare(): Unit = {
client = RedisClient.newRichClient(s"$DefaultRedisHost:$DefaultRedisPort")
}

@TearDown(Level.Iteration)
def check(): Unit = {
Await.result(client.release())
}

@Benchmark
def async(): Future[String] =
client.doRequest(FinaglePingBench.Ping) {
case BulkReply(message) Future.value(message.toString(Utf8))
}

@Benchmark
def sync(): String =
Await.result(client.doRequest(FinaglePingBench.Ping) {
case StatusReply(message) Future.value(message)
})
}
object FinaglePingBench {
object Ping extends Command {
val command = "PING"
val toChannelBuffer = RedisCodec.toUnifiedFormat(Seq(StringToChannelBuffer("PING")))
}
}
153 changes: 153 additions & 0 deletions benchmarks/finagle/src/main/scala/rx/redis/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
/*
* Copyright 2014 – 2015 Paul Horn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package rx.redis

import org.openjdk.jmh.profile.GCProfiler
import org.openjdk.jmh.results.format.ResultFormatType
import org.openjdk.jmh.runner.options._
import org.openjdk.jmh.runner.{ Defaults, NoBenchmarksException, Runner, RunnerException }

import annotation.tailrec
import scala.util.Try

object Main {

def run(options: Options): Unit = {
val runner = new Runner(options)
try {
runner.run()
} catch {
case e: NoBenchmarksException
Console.err.println("No matching benchmarks. Miss-spelled regexp?")
if (options.verbosity.orElse(Defaults.VERBOSITY) ne VerboseMode.EXTRA) {
Console.err.println("Use " + VerboseMode.EXTRA + " verbose mode to debug the pattern matching.")
} else {
runner.list()
}
case e: RunnerException
Console.err.print("ERROR: ")
e.printStackTrace(Console.err)
}
}

def main(args: Array[String]): Unit = {
Action(args) match {
case NoAction
case ListBenchmarks(opts)
new Runner(opts).list()
case RunBenchmarks(opts)
run(opts)
}
}

sealed trait Action
case class ListBenchmarks(opts: Options) extends Action
case class RunBenchmarks(opts: Options) extends Action
case object NoAction extends Action

object Action {
def apply(args: Array[String]): Action = {
loop(args.toList, None, OptionsParser()).map(_.run()).recover {
case e: CommandLineOptionException
Console.err.println("Error parsing command line:")
Console.err.println(" " + e.getMessage)
NoAction
}.get
}

@tailrec
private def loop(as: List[String], update: Option[String OptionsParser], opts: OptionsParser): Try[CustomOptions] = as match {
case Nil opts.run()
case x :: xs update match {
case Some(f) loop(xs, None, f(x))
case None x match {
case "-host" loop(xs, Some(opts.withHost), opts)
case "-port" loop(xs, Some(opts.withPort), opts)
case "-gc" loop(xs, None, opts.copy(enableProf = true))
case unknown loop(xs, None, opts.withArg(unknown))
}
}
}
}

case class CustomOptions(options: Options, cmdOptions: CommandLineOptions) {
def run(): Action =
if (cmdOptions.shouldHelp) {
cmdOptions.showHelp()
Console.err.println(
s"""
|Redis options:
|
| -host <string> The redis host to connect to.
| -port <int> The redis port to connect to.
| -gc Enable GC profiling.
""".stripMargin)
NoAction
} else if (cmdOptions.shouldList) {
ListBenchmarks(cmdOptions)
} else if (cmdOptions.shouldListProfilers) {
cmdOptions.listProfilers()
NoAction
} else if (cmdOptions.shouldListResultFormats) {
cmdOptions.listResultFormats()
NoAction
} else {
RunBenchmarks(options)
}
}

case class OptionsParser(
remaining: Vector[String] = Vector(),
enableProf: Boolean = false,
host: Option[String] = None,
port: Option[Int] = None) {

def withHost(h: String): OptionsParser =
copy(host = Some(h))

def withPort(p: String): OptionsParser =
copy(port = Try(p.toInt).toOption)

def withArg(x: String): OptionsParser =
copy(remaining = remaining :+ x)

def run(): Try[CustomOptions] = {
Try(new CommandLineOptions(remaining: _*)).map { cmdOptions
val builder = new OptionsBuilder()
.parent(cmdOptions)
.resultFormat(ResultFormatType.SCSV)
.shouldDoGC(true)

if (enableProf) {
builder.addProfiler(classOf[GCProfiler])
}

if (host.isDefined || port.isDefined) {
builder.jvmArgsAppend(toJmh: _*)
}

val options = builder.build()
CustomOptions(options, cmdOptions)
}
}

private def toJmh = List(
host.map(h s"-Drx.redis.host=$h").toList,
port.map(p s"-Drx.redis.port=$p").toList
).flatten
}
}
45 changes: 45 additions & 0 deletions benchmarks/finagle/src/main/scala/rx/redis/util/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2014 – 2015 Paul Horn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package rx.redis

import scala.util.{ Try, Properties }

import java.nio.charset.{ Charset, StandardCharsets }
import java.util.Locale

package object util {

val Utf8: Charset =
StandardCharsets.UTF_8

val RedisHost: Option[String] =
prop("rx.redis.host")

val RedisPort: Option[Int] =
prop("rx.redis.port").flatMap(p Try(p.toInt).toOption)

val DefaultRedisHost: String =
RedisHost.getOrElse("127.0.0.1")

val DefaultRedisPort: Int =
RedisPort.getOrElse(6379)

def prop(name: String): Option[String] = {
def upper: String = name.split('.').map(_.toUpperCase(Locale.ENGLISH)).mkString("_")
Properties.propOrNone(name).orElse(Properties.envOrNone(upper))
}
}
3 changes: 3 additions & 0 deletions benchmarks/scala-redis-nb/src/main/resources/application.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
akka {
loglevel = WARNING
}
Loading

0 comments on commit 58fe7cd

Please sign in to comment.