Selaa lähdekoodia

Updating PLAIN framework

Added pipelining support and db, update tests.
weltermann17 12 vuotta sitten
vanhempi
commit
df6ac7fa4f

+ 4 - 1
plain/benchmark_config

@@ -5,7 +5,10 @@
             "setup_file" : "setup",
             "json_url" : "/json",
             "plaintext_url": "/plaintext",
-            "port": 8080,
+            "db_url": "/db",
+            "query_url": "/db?queries=",
+            "update_url": "/update?queries=",
+            "port": 9080,
             "sort": 143
             }
         }

+ 16 - 10
plain/build.sbt

@@ -9,7 +9,7 @@ organization := "com.ibm"
 
 scalaVersion := "2.10.2"
 
-version := "1.0"
+version := "1.0.1"
 
 test in Compile := {}
 
@@ -27,25 +27,31 @@ scalacOptions in Compile ++= Seq(
 libraryDependencies ++= Seq(
   "org.scala-lang" % "scala-reflect" % "2.10.2",
   "org.reflections" % "reflections" % "0.9.8",
-  "com.typesafe" % "config" % "1.0.1",
-  "ch.qos.logback" % "logback-classic" % "1.0.12",
+  "com.typesafe" % "config" % "1.0.2",
+  "ch.qos.logback" % "logback-classic" % "1.0.13",
   "org.codehaus.janino" % "janino" % "2.6.1",
-  "com.lmax" % "disruptor" % "3.1.0",
-  "com.typesafe.akka" %% "akka-actor" % "2.1.4",
-  "com.typesafe.akka" %% "akka-slf4j" % "2.1.4",
+  "com.lmax" % "disruptor" % "3.1.1",
+  "com.typesafe.akka" %% "akka-actor" % "2.2.0",
+  "com.typesafe.akka" %% "akka-slf4j" % "2.2.0",
   "org.apache.commons" % "commons-lang3" % "3.1",
-  "org.apache.commons" % "commons-compress" % "1.4.1",
+  "org.apache.commons" % "commons-compress" % "1.5",
   "commons-io" % "commons-io" % "2.4",
-  "commons-net" % "commons-net" % "3.2",
-  "commons-codec" % "commons-codec" % "1.7",
+  "commons-net" % "commons-net" % "3.3",
+  "commons-codec" % "commons-codec" % "1.8",
   "com.googlecode.concurrentlinkedhashmap" % "concurrentlinkedhashmap-lru" % "1.3.2",
   "net.jpountz.lz4" % "lz4" % "1.1.2",
   "com.fasterxml.jackson.core" % "jackson-databind" % "2.2.2",
   "com.sun.jersey" % "jersey-json" % "1.17.1",
-  "org.jvnet.mimepull" % "mimepull" % "1.9.2",
+  "org.jvnet.mimepull" % "mimepull" % "1.9.3",
+  "org.apache.derby" % "derby" % "10.10.1.1",
+  "org.apache.derby" % "derbyclient" % "10.10.1.1",
+  "com.h2database" % "h2" % "1.3.172",
+  "mysql" % "mysql-connector-java" % "5.1.25",
   "javax.servlet" % "servlet-api" % "2.5"
 )
 
 Revolver.settings
 
 sbtassembly.Plugin.assemblySettings
+
+scalariformSettings

BIN
plain/lib/plain-library_2.10-1.0.1-SNAPSHOT.jar


+ 2 - 2
plain/setup.py

@@ -6,8 +6,8 @@ import os
 
 def start(args=None):
     subprocess.check_call("./sbt assembly", shell=True, cwd="plain")
-    subprocess.Popen("java -Xmx4g -Xss8m -jar target/scala-2.10/plain-benchmark-assembly-1.0.jar", cwd="plain", shell=True)
-    time.sleep(5)
+    subprocess.Popen("java -server -Xnoclassgc -XX:MaxPermSize=1g -XX:ReservedCodeCacheSize=384m -Xmx8g -Xss8m -Xmn4g -jar target/scala-2.10/plain-benchmark-assembly-1.0.1.jar", cwd="plain", shell=True)
+    time.sleep(10)
     return 0
 
 def stop():

+ 31 - 8
plain/src/main/resources/application.conf

@@ -2,17 +2,40 @@
 # application.conf
 #
 
-akka.event-handlers = [ "akka.event.slf4j.Slf4jEventHandler" ]
-akka.loglevel = WARNING
+akka {
+	loggers = [ "akka.event.slf4j.Slf4jLogger" ]
+	loglevel = OFF
+	stdout-loglevel = OFF
+}
 
-plain.logging.level = INFO
-plain.http.startup-servers = [ benchmark-server ]
+plain {
+	logging.level = INFO
+	aio.send-receive-buffer-size = 1m
+	http.startup-servers = [ benchmark-server ]
+	jdbc.startup-connection-factories = [ benchmark-mysql ]
+}
 
-benchmark-server.port-range = [ 8080 ]
-benchmark-server.dispatcher = benchmark-dispatcher
+benchmark-server {
+	port-range = [ 9080 ]
+	dispatcher = benchmark-dispatcher
+}
 
 benchmark-dispatcher.routes = [ 
-	{ uri = plaintext, resource-class-name = com.ibm.techempower.PlainTextResource }
-	{ uri = json, resource-class-name = com.ibm.techempower.JsonResource }
+	{ uri = plaintext, resource-class-name = com.ibm.techempower.PlainText }
+	{ uri = json, resource-class-name = com.ibm.techempower.Json }
+	{ uri = db, resource-class-name = com.ibm.techempower.Db }
+	{ uri = update, resource-class-name = com.ibm.techempower.Update }
 ]
 
+benchmark-mysql {
+	name = MysqlBenchmark
+	driver = mysql-5-6-12
+	datasource-settings {	
+		setUrl = "jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&dontTrackOpenResources=true&enableQueryTimeouts=false&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=1024&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=true&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true&poolPreparedStatements=true&maxOpenPreparedStatements=100"
+		setUser = "benchmarkdbuser"
+		setPassword = "benchmarkdbpass"
+	}	
+	min-pool-size = 16
+	max-pool-size = 128
+}
+

+ 81 - 0
plain/src/main/scala/com/ibm/techempower/Db.scala

@@ -0,0 +1,81 @@
+package com.ibm.techempower
+
+import java.util.concurrent.ThreadLocalRandom.{ current => random }
+
+import scala.language.implicitConversions
+import scala.language.postfixOps
+
+import com.ibm.plain.rest.{ Form, Resource }
+import com.ibm.plain.json.{ Json => J }
+import com.ibm.plain.jdbc.withConnection
+import com.ibm.plain.jdbc.ConnectionHelper._
+
+final class Db
+
+    extends DbResource {
+
+  Get { get(None) }
+
+  Get { form: Form => get(Some(form)) }
+
+}
+
+final class Update
+
+    extends DbResource {
+
+  Get { form: Form => update(form) }
+
+}
+
+sealed abstract class DbResource
+
+    extends Resource {
+
+  @inline protected[this] final def get(form: Option[Form]): J = {
+    var list: List[J] = Nil
+    val q = form match { case None => 1 case Some(f) => queries(f) }
+    withConnection(datasource) {
+      implicit connection => for (i <- 1 to q) { for (j <- selectsql << next <<! asJson) { list = j :: list } }
+    }
+    form match { case None => list.head case _ => J(list) }
+  }
+
+  @inline protected[this] final def update(form: Form): J = {
+    var list: List[J] = Nil
+    val q = queries(form)
+    withConnection(datasource) {
+      implicit connection =>
+        for (i <- 1 to q) {
+          val id = next
+          val randomNumber = next
+          updatesql << randomNumber << id <<!!;
+          list = asJson(id, randomNumber) :: list
+        }
+    }
+    J(list)
+  }
+
+  @inline private[this] final def queries(form: Form) = try {
+    form.get("queries").get.head.toInt match {
+      case q if 1 > q => 1
+      case q if 500 < q => 500
+      case q => q
+    }
+  } catch {
+    case _: Throwable => 1
+  }
+
+  @inline private[this] final def asJson = (r: RichResultSet) => J(Map("id" -> r.nextInt.get, "randomNumber" -> r.nextInt.get))
+
+  @inline private[this] final def asJson(id: Int, randomNumber: Int) = J(Map("id" -> id, "randomNumber" -> randomNumber))
+
+  @inline private[this] final def next = random.nextInt(1, 10001)
+
+  private[this] final val selectsql = "select id, randomNumber from World where id = ?"
+
+  private[this] final val updatesql = "update World set randomNumber = ? where id = ?"
+
+  private[this] final val datasource = "MysqlBenchmark"
+
+}

+ 12 - 0
plain/src/main/scala/com/ibm/techempower/Json.scala

@@ -0,0 +1,12 @@
+package com.ibm.techempower
+
+import com.ibm.plain.rest.Resource
+import com.ibm.plain.json.{ Json => J }
+
+final class Json
+
+    extends Resource {
+
+  Get { J(Map("message" -> "Hello, World!")) }
+
+}

+ 0 - 12
plain/src/main/scala/com/ibm/techempower/JsonResource.scala

@@ -1,12 +0,0 @@
-package com.ibm.techempower
-
-import com.ibm.plain.rest.Resource
-import com.ibm.plain.json.Json
-
-final class JsonResource
-
-  extends Resource {
-
-  Get { Json(Map("message" -> "Hello, World!")) }
-
-}

+ 22 - 0
plain/src/main/scala/com/ibm/techempower/PlainText.scala

@@ -0,0 +1,22 @@
+package com.ibm.techempower
+
+import java.nio.ByteBuffer
+
+import com.ibm.plain.rest.Resource
+import com.ibm.plain.text.`UTF-8`
+
+final class PlainText
+
+    extends Resource {
+
+  import PlainText._
+
+  Get { hello }
+
+}
+
+object PlainText {
+
+  private final val hello = "Hello, World!".getBytes(`UTF-8`)
+
+}

+ 0 - 20
plain/src/main/scala/com/ibm/techempower/PlainTextResource.scala

@@ -1,20 +0,0 @@
-package com.ibm.techempower
-
-import com.ibm.plain.rest.Resource
-import com.ibm.plain.text.`UTF-8`
-
-final class PlainTextResource
-
-  extends Resource {
-  
-  import PlainTextResource._
-
-  Get { hello }
-
-}
-
-object PlainTextResource {
-  
-  final val hello = "Hello, World!".getBytes(`UTF-8`)  
-  
-}