Ver código fonte

merge from master

nam 9 anos atrás
pai
commit
e5c83d53ae
80 arquivos alterados com 1182 adições e 447 exclusões
  1. 2 0
      .travis.yml
  2. 1 1
      frameworks/Clojure/luminus/hello/project.clj
  3. 2 2
      frameworks/Clojure/luminus/hello/src/hello/db/core.clj
  4. 1 1
      frameworks/D/vibed/dub.json
  5. 3 3
      frameworks/D/vibed/dub.selections.json
  6. 70 97
      frameworks/Go/go-raw-mongodb/src/hello/hello.go
  7. 19 0
      frameworks/Go/kami/README.md
  8. 28 0
      frameworks/Go/kami/benchmark_config.json
  9. 10 0
      frameworks/Go/kami/setup.sh
  10. 191 0
      frameworks/Go/kami/src/kami/server.go
  11. 14 0
      frameworks/Go/kami/templates/fortune.html
  12. 9 0
      frameworks/Go/kami/templates/layout.html
  13. 33 0
      frameworks/Java/bayou/README.md
  14. 24 0
      frameworks/Java/bayou/benchmark_config.json
  15. 81 0
      frameworks/Java/bayou/pom.xml
  16. 7 0
      frameworks/Java/bayou/setup.sh
  17. 1 0
      frameworks/Java/bayou/source_code
  18. 59 0
      frameworks/Java/bayou/src/main/java/bayou/BayouServer.java
  19. 4 4
      frameworks/Java/curacao/pom.xml
  20. 1 1
      frameworks/Java/dropwizard/pom.xml
  21. 2 2
      frameworks/Java/netty/pom.xml
  22. 1 1
      frameworks/Java/servlet/pom.xml
  23. 5 1
      frameworks/Java/undertow-edge/pom.xml
  24. 1 1
      frameworks/Java/undertow/pom.xml
  25. 1 1
      frameworks/Java/vertx-web/Readme.md
  26. 26 5
      frameworks/Java/vertx-web/benchmark_config.json
  27. 2 8
      frameworks/Java/vertx-web/pom.xml
  28. 1 1
      frameworks/Java/vertx-web/setup.sh
  29. 5 4
      frameworks/Java/vertx-web/src/main/conf/config.json
  30. 99 32
      frameworks/Java/vertx-web/src/main/java/io/vertx/benchmark/App.java
  31. 1 1
      frameworks/Java/vertx/pom.xml
  32. 1 1
      frameworks/Java/wildfly-ee7/benchmark_config.json
  33. 2 1
      frameworks/Perl/mojolicious/.gitignore
  34. 10 2
      frameworks/Perl/mojolicious/app.pl
  35. 35 29
      frameworks/Perl/mojolicious/cpanfile.snapshot
  36. 8 0
      frameworks/Python/asyncio/aiohttp.web/etc/hello/main/main.yaml
  37. 23 0
      frameworks/Python/asyncio/aiohttp.web/hello/__init__.py
  38. 33 1
      frameworks/Python/asyncio/aiohttp.web/hello/endpoints/world.py
  39. 56 0
      frameworks/Python/asyncio/aiohttp.web/hello/services/mysql.py
  40. 20 0
      frameworks/Python/asyncio/benchmark_config.json
  41. 2 0
      frameworks/Python/asyncio/requirements.txt
  42. 1 2
      frameworks/Rust/hyper/Cargo.toml
  43. 13 13
      frameworks/Rust/hyper/src/main.rs
  44. 3 3
      frameworks/Rust/iron/Cargo.toml
  45. 1 1
      frameworks/Rust/iron/setup.sh
  46. 14 10
      frameworks/Rust/iron/src/main.rs
  47. 2 2
      frameworks/Rust/nickel/Cargo.toml
  48. 1 1
      frameworks/Rust/nickel/setup.sh
  49. 7 4
      frameworks/Rust/nickel/src/main.rs
  50. 2 3
      frameworks/Scala/akka-http/build.sbt
  51. 1 1
      frameworks/Scala/akka-http/project/build.properties
  52. 3 11
      frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Bootstrap.scala
  53. 1 1
      frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/DbHandler.scala
  54. 1 1
      frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/JsonHandler.scala
  55. 1 1
      frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/QueriesHandler.scala
  56. 1 1
      frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/UpdatesHandler.scala
  57. BIN
      frameworks/Scala/finagle/.cache
  58. 0 34
      frameworks/Scala/finagle/.classpath
  59. 0 12
      frameworks/Scala/finagle/.project
  60. 3 2
      frameworks/Scala/finagle/benchmark_config.json
  61. 3 7
      frameworks/Scala/finagle/build.sbt
  62. 1 1
      frameworks/Scala/finagle/setup.sh
  63. 2 2
      frameworks/Scala/finagle/source_code
  64. 52 0
      frameworks/Scala/finagle/src/main/scala/Main.scala
  65. 0 105
      frameworks/Scala/finagle/src/main/scala/com/falmarri/finagle/Finagle.scala
  66. 5 5
      frameworks/Scala/finch/build.sbt
  67. 20 16
      frameworks/Scala/finch/src/main/scala/WebServer.scala
  68. 11 0
      frameworks/Scala/fintrospect/.gitignore
  69. 22 0
      frameworks/Scala/fintrospect/README.md
  70. 23 0
      frameworks/Scala/fintrospect/benchmark_config.json
  71. 21 0
      frameworks/Scala/fintrospect/build.sbt
  72. 4 0
      frameworks/Scala/fintrospect/project/build.properties
  73. 1 0
      frameworks/Scala/fintrospect/project/plugins.sbt
  74. 7 0
      frameworks/Scala/fintrospect/setup.sh
  75. 52 0
      frameworks/Scala/fintrospect/src/main/scala/FintrospectBenchmarkServer.scala
  76. 1 1
      frameworks/Scala/http4s/build.sbt
  77. 3 2
      frameworks/Scala/play2-scala/play2-scala/app/controllers/Application.scala
  78. 1 1
      frameworks/Scala/scruffy/src/main/scala/scruffy/examples/Test2Endpoint.scala
  79. 1 1
      frameworks/Ur/urweb/setup.sh
  80. 3 3
      toolset/setup/linux/languages/rust.sh

+ 2 - 0
.travis.yml

@@ -70,6 +70,7 @@ env:
     - "TESTDIR=Haskell/yesod"
     - "TESTDIR=Java/activeweb"
     - "TESTDIR=Java/baratine"
+    - "TESTDIR=Java/bayou"
     - "TESTDIR=Java/comsat-servlet"
     - "TESTDIR=Java/comsat-webactors"
     - "TESTDIR=Java/curacao"
@@ -179,6 +180,7 @@ env:
     - "TESTDIR=Scala/akka-http"
     - "TESTDIR=Scala/colossus"
     - "TESTDIR=Scala/finagle"
+    - "TESTDIR=Scala/fintrospect"
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/plain"
     - "TESTDIR=Scala/play2-scala"

+ 1 - 1
frameworks/Clojure/luminus/hello/project.clj

@@ -24,7 +24,7 @@
                  [luminus-nrepl "0.1.2"]
                  [migratus "0.8.8"]
                  [conman "0.2.9"]
-                 [org.postgresql/postgresql "9.4-1206-jdbc4"]
+                 [org.postgresql/postgresql "9.4.1208"]
                  [org.webjars/webjars-locator-jboss-vfs "0.1.0"]
                  [luminus-immutant "0.1.0"]]
 

+ 2 - 2
frameworks/Clojure/luminus/hello/src/hello/db/core.clj

@@ -6,7 +6,7 @@
     [environ.core :refer [env]]
     [mount.core :refer [defstate]])
   (:import org.postgresql.util.PGobject
-           org.postgresql.jdbc4.Jdbc4Array
+           org.postgresql.jdbc.PgArray
            clojure.lang.IPersistentMap
            clojure.lang.IPersistentVector
            [java.sql
@@ -48,7 +48,7 @@
   Timestamp
   (result-set-read-column [v _ _] (to-date v))
 
-  Jdbc4Array
+  PgArray
   (result-set-read-column [v _ _] (vec (.getArray v)))
 
   PGobject

+ 1 - 1
frameworks/D/vibed/dub.json

@@ -3,7 +3,7 @@
   "description": "A simple vibe.d server application.",
   "copyright": "Copyright © 2015, jin",
   "authors": ["jin", "Sönke Ludwig"],
-  "dependencies": { "vibe-d": "~>0.7.26" },
+  "dependencies": { "vibe-d": "~>0.7.28" },
   "versions": ["VibeDefaultMain"],
   "targetType": "executable",
   "sourcePaths": [],

+ 3 - 3
frameworks/D/vibed/dub.selections.json

@@ -1,11 +1,11 @@
 {
 	"fileVersion": 1,
 	"versions": {
-		"memutils": "0.4.3",
-		"vibe-d": "0.7.26",
+		"memutils": "0.4.4",
+		"vibe-d": "0.7.28",
 		"libevent": "2.0.1+2.0.16",
 		"openssl": "1.1.4+1.0.1g",
-		"libasync": "0.7.5",
+		"libasync": "0.7.8",
 		"libev": "5.0.0+4.04"
 	}
 }

+ 70 - 97
frameworks/Go/go-raw-mongodb/src/hello/hello.go

@@ -8,7 +8,6 @@ import (
 	"log"
 	"math/rand"
 	"net/http"
-	"runtime"
 	"sort"
 	"strconv"
 )
@@ -20,7 +19,8 @@ const (
 )
 
 var (
-	tmpl = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
+	tmpl            = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
+	helloWorldBytes = []byte(helloWorldString)
 
 	database *mgo.Database
 	fortunes *mgo.Collection
@@ -32,12 +32,12 @@ type Message struct {
 }
 
 type World struct {
-	Id           uint16 `bson:"id" json:"id"`
+	Id           uint16 `bson:"_id" json:"id"`
 	RandomNumber uint16 `bson:"randomNumber" json:"randomNumber"`
 }
 
 type Fortune struct {
-	Id      uint16 `bson:"id" json:"id"`
+	Id      uint16 `bson:"_id" json:"id"`
 	Message string `bson:"message" json:"message"`
 }
 
@@ -58,28 +58,21 @@ func (s ByMessage) Less(i, j int) bool {
 }
 
 func main() {
-	runtime.GOMAXPROCS(runtime.NumCPU())
-	if session, err := mgo.Dial(connectionString); err != nil {
+	session, err := mgo.Dial(connectionString)
+	if err != nil {
 		log.Fatalf("Error opening database: %v", err)
-	} else {
-		defer session.Close()
-		session.SetPoolLimit(5)
-		database = session.DB("hello_world")
-		worlds = database.C("world")
-		fortunes = database.C("fortune")
-		http.HandleFunc("/json", jsonHandler)
-		http.HandleFunc("/db", dbHandler)
-		http.HandleFunc("/fortune", fortuneHandler)
-		http.HandleFunc("/queries", queriesHandler)
-		http.HandleFunc("/update", updateHandler)
-		http.HandleFunc("/plaintext", plaintextHandler)
-		http.ListenAndServe(":8080", nil)
 	}
-}
-
-// Helper for random numbers
-func getRandomNumber() uint16 {
-	return uint16(rand.Intn(worldRowCount) + 1)
+	defer session.Close()
+	database = session.DB("hello_world")
+	worlds = database.C("world")
+	fortunes = database.C("fortune")
+	http.HandleFunc("/json", jsonHandler)
+	http.HandleFunc("/db", dbHandler)
+	http.HandleFunc("/fortune", fortuneHandler)
+	http.HandleFunc("/queries", queriesHandler)
+	http.HandleFunc("/update", updateHandler)
+	http.HandleFunc("/plaintext", plaintextHandler)
+	http.ListenAndServe(":8080", nil)
 }
 
 // Test 1: JSON serialization
@@ -89,117 +82,97 @@ func jsonHandler(w http.ResponseWriter, r *http.Request) {
 	json.NewEncoder(w).Encode(&Message{helloWorldString})
 }
 
+// Helper for random numbers
+func getRandomNumber() uint16 {
+	return uint16(rand.Intn(worldRowCount) + 1)
+}
+
+// Test 2: Single database query
 func dbHandler(w http.ResponseWriter, r *http.Request) {
 	var world World
-	query := bson.M{"id": getRandomNumber()}
-	if worlds != nil {
-		if err := worlds.Find(query).One(&world); err != nil {
-			log.Fatalf("Error finding world with id: %s", err.Error())
-			return
-		} else {
-			w.Header().Set("Content-Type", "application/json")
-			w.Header().Set("Server", "go-mongodb")
-			json.NewEncoder(w).Encode(&world)
-			return
-		}
-	} else {
-		log.Fatal("Collection not initialized properly")
+	query := bson.M{"_id": getRandomNumber()}
+	if err := worlds.Find(query).One(&world); err != nil {
+		log.Fatalf("Error finding world with id: %s", err.Error())
 	}
+	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Server", "go-mongodb")
+	json.NewEncoder(w).Encode(&world)
 }
 
-func queriesHandler(w http.ResponseWriter, r *http.Request) {
+// Helper for getting the "queries" parameter
+func getQueriesParam(r *http.Request) int {
 	n := 1
 	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
 		n, _ = strconv.Atoi(nStr)
 	}
 
-	if n > 500 {
+	if n < 1 {
+		n = 1
+	} else if n > 500 {
 		n = 500
 	}
 
-	w.Header().Set("Content-Type", "application/json")
-	w.Header().Set("Server", "go-mongodb")
-	encoder := json.NewEncoder(w)
+	return n
+}
+
+// Test 3: Multiple database queries
+func queriesHandler(w http.ResponseWriter, r *http.Request) {
+	n := getQueriesParam(r)
+	world := make([]World, n)
 
-	if n <= 1 {
-		result := make([]World, 1)
-		query := bson.M{"id": getRandomNumber()}
-		if err := worlds.Find(query).One(&result[0]); err != nil {
+	for i := 0; i < n; i++ {
+		query := bson.M{"_id": getRandomNumber()}
+		if err := worlds.Find(query).One(&world[i]); err != nil {
 			log.Fatalf("Error finding world with id: %s", err.Error())
-			return
 		}
-		encoder.Encode(&result)
-	} else {
-		result := make([]World, n)
-		for i := 0; i < n; i++ {
-			query := bson.M{"id": getRandomNumber()}
-			if err := worlds.Find(query).One(&result[i]); err != nil {
-				log.Fatalf("Error finding world with id: %s", err.Error())
-				return
-			}
-		}
-		encoder.Encode(&result)
 	}
+
+	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Server", "go-mongodb")
+	json.NewEncoder(w).Encode(world)
 }
 
+// Test 4: Fortunes
 func fortuneHandler(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/html")
+	w.Header().Set("Content-Type", "text/html; charset=utf-8")
 	w.Header().Set("Server", "go-mongodb")
 	f := make(Fortunes, 16)
 	if err := fortunes.Find(nil).All(&f); err == nil {
-		f = append(f, Fortune{
-			Message: "Additional fortune added at request time.",
-		})
+		f = append(f, Fortune{Message: "Additional fortune added at request time."})
 		sort.Sort(ByMessage{f})
 		if err := tmpl.Execute(w, f); err != nil {
 			http.Error(w, err.Error(), http.StatusInternalServerError)
 		}
+	} else {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
 	}
-
 }
 
+// Test 5: Database updates
 func updateHandler(w http.ResponseWriter, r *http.Request) {
-	n := 1
-	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
-		n, _ = strconv.Atoi(nStr)
-	}
+	n := getQueriesParam(r)
+	world := make([]World, n)
 
-	w.Header().Set("Content-Type", "application/json")
-	w.Header().Set("Server", "go-mongodb")
-	encoder := json.NewEncoder(w)
-
-	if n <= 1 {
-		result := make([]World, 1)
-		colQuery := bson.M{"id": getRandomNumber()}
-		update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
-		if err := worlds.Update(colQuery, update); err != nil {
-			log.Fatalf("Error updating world with id: %s", err.Error())
-		} else {
-			result[0].Id = colQuery["id"].(uint16)
-			result[0].RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
-		}
-		encoder.Encode(&result)
-	} else {
-		if n > 500 {
-			n = 500
+	for i := 0; i < n; i++ {
+		query := bson.M{"_id": getRandomNumber()}
+		if err := worlds.Find(query).One(&world[i]); err != nil {
+			log.Fatalf("Error finding world with id: %s", err.Error())
 		}
-		result := make([]World, n)
-		for i := 0; i < n; i++ {
-			colQuery := bson.M{"id": getRandomNumber()}
-			update := bson.M{"$set": bson.M{"randomNumber": getRandomNumber()}}
-			if err := worlds.Update(colQuery, update); err != nil {
-				log.Fatalf("Error updating world with id: %s", err.Error())
-			} else {
-				result[i].Id = colQuery["id"].(uint16)
-				result[i].RandomNumber = update["$set"].(bson.M)["randomNumber"].(uint16)
-			}
+		world[i].RandomNumber = getRandomNumber()
+		update := bson.M{"$set": bson.M{"randomNumber": world[i].RandomNumber}}
+		if err := worlds.Update(query, update); err != nil {
+			log.Fatalf("Error updating world with id: %s", err.Error())
 		}
-		encoder.Encode(&result)
 	}
+
+	w.Header().Set("Content-Type", "application/json")
+	w.Header().Set("Server", "Go")
+	json.NewEncoder(w).Encode(&world)
 }
 
+// Test 6: Plaintext
 func plaintextHandler(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Content-Type", "text/plain")
 	w.Header().Set("Server", "go-mongodb")
-	w.Write([]byte(helloWorldString))
+	w.Write(helloWorldBytes)
 }

+ 19 - 0
frameworks/Go/kami/README.md

@@ -0,0 +1,19 @@
+# [kame](https://github.com/guregu/kami) (Go) Benchmarking Test
+
+This is the go portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+
+"kami (神) is a tiny web framework using [x/net/context](https://blog.golang.org/context) for request context and [HttpRouter](https://github.com/julienschmidt/httprouter) for routing. It includes a simple system for running hierarchical middleware before and after requests, in addition to log and panic hooks."
+
+
+### Source
+* [All test source](src/kami/server.go)
+
+## Test URLs
+
+    http://localhost:8080/json
+    http://localhost:8080/db
+    http://localhost:8080/queries?queries=[1-500]
+    http://localhost:8080/fortunes
+    http://localhost:8080/updates?queries=[1-500]
+    http://localhost:8080/plaintext

+ 28 - 0
frameworks/Go/kami/benchmark_config.json

@@ -0,0 +1,28 @@
+{
+  "framework": "kami",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MySQL",
+      "framework": "kami",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "kami",
+      "notes": "",
+      "versus": "go"
+    }
+  }]
+}

+ 10 - 0
frameworks/Go/kami/setup.sh

@@ -0,0 +1,10 @@
+#!/bin/bash
+
+sed -i 's|tcp(.*:3306)|tcp('"${DBHOST}"':3306)|g' src/kami/server.go
+
+fw_depends go
+
+go get github.com/go-sql-driver/mysql
+go get github.com/guregu/kami
+
+go run src/kami/server.go &

+ 191 - 0
frameworks/Go/kami/src/kami/server.go

@@ -0,0 +1,191 @@
+package main
+
+import (
+	"database/sql"
+	"encoding/json"
+	"flag"
+	"html/template"
+	"log"
+	"math/rand"
+	"net/http"
+	"sort"
+	"strconv"
+
+	"golang.org/x/net/context"
+
+	_ "github.com/go-sql-driver/mysql"
+	"github.com/guregu/kami"
+)
+
+type Message struct {
+	Message string `json:"message"`
+}
+
+type World struct {
+	Id           uint16 `json:"id"`
+	RandomNumber uint16 `json:"randomNumber"`
+}
+
+type Fortune struct {
+	Id      uint16 `json:"id"`
+	Message string `json:"message"`
+}
+
+// Databases
+const (
+	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world?interpolateParams=true"
+	worldSelect        = "SELECT id, randomNumber FROM World WHERE id = ?"
+	worldUpdate        = "UPDATE World SET randomNumber = ? WHERE id = ?"
+	fortuneSelect      = "SELECT id, message FROM Fortune;"
+	worldRowCount      = 10000
+	maxConnectionCount = 256
+)
+
+const helloWorldString = "Hello, World!"
+
+var (
+	// Templates
+	tmpl = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
+
+	// Database
+	db *sql.DB
+
+	helloWorldBytes = []byte(helloWorldString)
+)
+
+func main() {
+	var err error
+	db, err = sql.Open("mysql", connectionString)
+	if err != nil {
+		log.Fatalf("Error opening database: %v", err)
+	}
+	db.SetMaxIdleConns(maxConnectionCount)
+
+	flag.Set("bind", ":8080")
+
+	kami.Use("/", serverMiddleware)
+	kami.Get("/json", jsonHandler)
+	kami.Get("/db", dbHandler)
+	kami.Get("/queries", queriesHandler)
+	kami.Get("/fortunes", fortuneHandler)
+	kami.Get("/updates", updateHandler)
+	kami.Get("/plaintext", plaintextHandler)
+	kami.Serve()
+}
+
+// serverMiddleware will set the Server header on all outgoing requests
+func serverMiddleware(ctx context.Context, w http.ResponseWriter, _ *http.Request) context.Context {
+	w.Header().Set("Server", "kami")
+	return ctx
+}
+
+// jsonHandler implements Test 1: JSON Serializer
+func jsonHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(&Message{helloWorldString})
+}
+
+// Test 2: Single database query
+func dbHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+	var world World
+	err := db.QueryRow(worldSelect, rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber)
+	if err != nil {
+		log.Fatalf("Error scanning world row: %s", err.Error())
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(&world)
+}
+
+// Test 3: Multiple database queries
+func queriesHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+	n := 1
+	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
+		n, _ = strconv.Atoi(nStr)
+	}
+
+	if n < 1 {
+		n = 1
+	} else if n > 500 {
+		n = 500
+	}
+
+	world := make([]World, n)
+	for i := 0; i < n; i++ {
+		err := db.QueryRow(worldSelect, rand.Intn(worldRowCount)+1).Scan(&world[i].Id, &world[i].RandomNumber)
+		if err != nil {
+			log.Fatalf("Error scanning world row: %s", err.Error())
+		}
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(world)
+}
+
+// Test 4: Fortunes
+func fortuneHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+	rows, err := db.Query(fortuneSelect)
+	if err != nil {
+		log.Fatalf("Error preparing statement: %v", err)
+	}
+
+	fortunes := make(Fortunes, 0, 16)
+	for rows.Next() { //Fetch rows
+		fortune := Fortune{}
+		if err := rows.Scan(&fortune.Id, &fortune.Message); err != nil {
+			log.Fatalf("Error scanning fortune row: %s", err.Error())
+		}
+		fortunes = append(fortunes, &fortune)
+	}
+	rows.Close()
+	fortunes = append(fortunes, &Fortune{Message: "Additional fortune added at request time."})
+
+	sort.Sort(ByMessage{fortunes})
+	w.Header().Set("Content-Type", "text/html")
+	if err := tmpl.Execute(w, fortunes); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+}
+
+// Test 5: Database updates
+func updateHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+	n := 1
+	if nStr := r.URL.Query().Get("queries"); len(nStr) > 0 {
+		n, _ = strconv.Atoi(nStr)
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	encoder := json.NewEncoder(w)
+
+	if n < 1 {
+		n = 1
+	} else if n > 500 {
+		n = 500
+	}
+	world := make([]World, n)
+	for i := 0; i < n; i++ {
+		if err := db.QueryRow(worldSelect, rand.Intn(worldRowCount)+1).Scan(&world[i].Id, &world[i].RandomNumber); err != nil {
+			log.Fatalf("Error scanning world row: %s", err.Error())
+		}
+		world[i].RandomNumber = uint16(rand.Intn(worldRowCount) + 1)
+		if _, err := db.Exec(worldUpdate, world[i].RandomNumber, world[i].Id); err != nil {
+			log.Fatalf("Error updating world row: %s", err.Error())
+		}
+	}
+	encoder.Encode(world)
+}
+
+// Test 6: Plaintext
+func plaintextHandler(ctx context.Context, w http.ResponseWriter, r *http.Request) {
+	w.Header().Set("Content-Type", "text/plain")
+	w.Write(helloWorldBytes)
+}
+
+type Fortunes []*Fortune
+
+func (s Fortunes) Len() int      { return len(s) }
+func (s Fortunes) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+type ByMessage struct{ Fortunes }
+
+func (s ByMessage) Less(i, j int) bool { return s.Fortunes[i].Message < s.Fortunes[j].Message }

+ 14 - 0
frameworks/Go/kami/templates/fortune.html

@@ -0,0 +1,14 @@
+{{define "content"}}
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+{{range .}}
+<tr>
+<td>{{.Id}}</td>
+<td>{{.Message}}</td>
+</tr>
+{{end}}
+</table>
+{{end}}

+ 9 - 0
frameworks/Go/kami/templates/layout.html

@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+{{template "content" .}}
+</body>
+</html>

+ 33 - 0
frameworks/Java/bayou/README.md

@@ -0,0 +1,33 @@
+# bayou.io Benchmarking Test
+
+This is the `bayou.io` portion of [TechEmpower/FrameworkBenchmarks](https://github.com/TechEmpower/FrameworkBenchmarks).
+
+
+
+## About bayou.io
+
+`bayou.io` is an async http server/client library for Java.
+
+Version: [bayou-1.0.0](http://bayou.io/code.html)
+
+GitHub: <https://github.com/zhong-j-yu/bayou>
+
+More Info: <http://bayou.io/info.html>
+
+
+
+
+## Source for Tests
+
+Json and Plaintext test source:
+
+* [BayouServer.java](src/main/java/bayou/BayouServer.java)
+
+
+
+## Test URLs
+
+* json: <http://localhost:8080/json>
+
+* plaintext: <http://localhost:8080/plaintext>
+

+ 24 - 0
frameworks/Java/bayou/benchmark_config.json

@@ -0,0 +1,24 @@
+{
+    "framework": "bayou",
+    "tests": [{
+        "default": {
+            "setup_file": "setup",
+            "json_url": "/json",
+            "plaintext_url": "/plaintext",
+            "port": 8080,
+            "approach": "Realistic",
+            "classification": "Platform",
+            "database": "None",
+            "framework": "bayou.io",
+            "language": "Java",
+            "orm": "Raw",
+            "platform": "bayou.io",
+            "webserver": "None",
+            "os": "Linux",
+            "database_os": "Linux",
+            "display_name": "bayou.io",
+            "notes": "",
+            "versus": ""
+        }
+    }]
+}

+ 81 - 0
frameworks/Java/bayou/pom.xml

@@ -0,0 +1,81 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>io.bayou</groupId>
+    <artifactId>bayou_TFB</artifactId>
+    <version>0.1</version>
+
+
+
+    <!-- see https://jitpack.io/ -->
+    <repositories>
+        <repository>
+            <id>jitpack.io</id>
+            <url>https://jitpack.io</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+
+        <!-- see https://jitpack.io/ -->
+        <dependency>
+            <groupId>com.github.zhong-j-yu</groupId>
+            <artifactId>bayou</artifactId>
+            <version>1.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.6.0</version>
+        </dependency>
+
+    </dependencies>
+
+
+
+    <build>
+        <plugins>
+
+            <!-- require Java 8 -->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.3</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <manifest>
+                            <mainClass>bayou.BayouServer</mainClass>
+                        </manifest>
+                    </archive>
+                    <descriptorRefs>
+                        <descriptorRef>jar-with-dependencies</descriptorRef>
+                    </descriptorRefs>
+                </configuration>
+                <executions>
+                    <execution>
+                        <id>make-assembly</id> <!-- this is used for inheritance merges -->
+                        <phase>package</phase> <!-- bind to the packaging phase -->
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+    </build>
+
+
+
+</project>

+ 7 - 0
frameworks/Java/bayou/setup.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends java maven
+
+mvn clean compile assembly:single
+cd target
+java -jar bayou_TFB-0.1-jar-with-dependencies.jar &

+ 1 - 0
frameworks/Java/bayou/source_code

@@ -0,0 +1 @@
+./bayou/src/main/java/bayou/BayouServer.java

+ 59 - 0
frameworks/Java/bayou/src/main/java/bayou/BayouServer.java

@@ -0,0 +1,59 @@
+package bayou;
+
+import bayou.http.*;
+import bayou.mime.ContentType;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.util.Collections;
+
+/**
+ *  bayou.io HTTP Server for TechEmpower/FrameworkBenchmarks
+ */
+public class BayouServer
+{
+    public static void main(String[] args) throws Exception
+    {
+        System.setProperty("bayou.http.server.pipeline", "true" ); // favor pipelined requests
+        System.setProperty("bayou.http.server.fiber",    "false"); // fiber not needed in this app
+
+        byte[] bytesHelloWorld = "Hello, World!".getBytes();
+
+        HttpServer server = new HttpServer(request->
+        {
+            switch(request.uri())
+            {
+                case "/json" :
+                    Object obj = Collections.singletonMap("message", "Hello, World!");
+                    return new SimpleHttpResponse(HttpStatus.c200_OK, ContentType.json, toJson(obj));
+
+                case "/plaintext" :
+                    return new SimpleHttpResponse(HttpStatus.c200_OK, ContentType.text_plain, bytesHelloWorld);
+
+                default :
+                    return HttpResponse.text(404, "Not Found -- ", request.uri() );
+            }
+        });
+
+        server.conf().setProxyDefaults();  // disable some non-essential features
+        //server.conf().trafficDump(System.out::print);
+
+        server.start();
+    }
+
+
+    // json - jackson -------------------------------------------------------------------------------------
+    // pretty slow; don't care much.
+
+    static final ObjectMapper objectMapper = new ObjectMapper();
+    static byte[] toJson(Object obj)
+    {
+        try{
+            return objectMapper.writeValueAsBytes(obj);
+        }catch (JsonProcessingException e){
+            throw new RuntimeException(e);  // HTTP 500 Internal Error
+        }
+    }
+
+}

+ 4 - 4
frameworks/Java/curacao/pom.xml

@@ -20,12 +20,12 @@
         <dependency>
             <groupId>curacao</groupId>
             <artifactId>curacao</artifactId>
-            <version>4.0.0</version>
+            <version>4.0.4</version>
         </dependency>
         <dependency>
             <groupId>curacao</groupId>
             <artifactId>curacao-gson</artifactId>
-            <version>4.0.0</version>
+            <version>4.0.4</version>
         </dependency>
 
         <!-- Servlet -->
@@ -40,12 +40,12 @@
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-core</artifactId>
-            <version>1.1.3</version>
+            <version>1.1.5</version>
         </dependency>
         <dependency>
             <groupId>ch.qos.logback</groupId>
             <artifactId>logback-classic</artifactId>
-            <version>1.1.3</version>
+            <version>1.1.5</version>
         </dependency>
 
     </dependencies>

+ 1 - 1
frameworks/Java/dropwizard/pom.xml

@@ -13,7 +13,7 @@
         <dropwizard.version>0.8.1</dropwizard.version>
         <mysql-connector-java.version>5.1.35</mysql-connector-java.version>
         <mongojack.version>2.3.0</mongojack.version>
-        <postgres-jdbc.version>9.4-1201-jdbc41</postgres-jdbc.version>
+        <postgres-jdbc.version>9.4.1208</postgres-jdbc.version>
         <dropwizard.java8.version>0.8.0-1</dropwizard.java8.version>
 
         <main.class>com.example.helloworld.HelloWorldService</main.class>

+ 2 - 2
frameworks/Java/netty/pom.xml

@@ -12,12 +12,12 @@
 		<dependency>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-codec-http</artifactId>
-			<version>4.0.33.Final</version>
+			<version>4.0.34.Final</version>
 		</dependency>
 		<dependency>
 			<groupId>io.netty</groupId>
 			<artifactId>netty-transport-native-epoll</artifactId>
-			<version>4.0.33.Final</version>
+			<version>4.0.34.Final</version>
 			<classifier>linux-x86_64</classifier>
 		</dependency>
 		<dependency>

+ 1 - 1
frameworks/Java/servlet/pom.xml

@@ -20,7 +20,7 @@
 	<dependency>
 	    <groupId>org.postgresql</groupId>
 	    <artifactId>postgresql</artifactId>
-	    <version>9.4-1200-jdbc41</version>
+	    <version>9.4.1208</version>
 	</dependency>
             
 

+ 5 - 1
frameworks/Java/undertow-edge/pom.xml

@@ -13,6 +13,10 @@
     <artifactId>undertow-edge</artifactId>
     <version>0.1</version>
 
+    <properties>
+        <postgres-jdbc.version>9.4.1208</postgres-jdbc.version>
+    </properties>
+
     <dependencies>
         <!-- Web server -->
         <dependency>
@@ -45,7 +49,7 @@
         <dependency>
             <groupId>org.postgresql</groupId>
 	    <artifactId>postgresql</artifactId>
-            <version>9.4-1200-jdbc41</version>
+            <version>${postgres-jdbc.version}</version>
 	</dependency>
         <dependency>
             <groupId>org.mongodb</groupId>

+ 1 - 1
frameworks/Java/undertow/pom.xml

@@ -36,7 +36,7 @@
         <dependency>
             <groupId>org.postgresql</groupId>
 	    <artifactId>postgresql</artifactId>
-            <version>9.4-1200-jdbc41</version>
+            <version>9.4.1208</version>
 	</dependency>
         <dependency>
             <groupId>org.mongodb</groupId>

+ 1 - 1
frameworks/Java/vertx-web/Readme.md

@@ -56,7 +56,7 @@ repo and wrk is on your path. The final argument after the `--` is the desired p
 plaintext scenario at a pipeline depth of 16, [just like the Techempower Benchmarks](https://github.com/TechEmpower/FrameworkBenchmarks/blob/6594d32db618c6ca65e0106c5adf2671f7b63654/toolset/benchmark/framework_test.py#L640).
 
 ```
-wrk -c 256 -t 32 -d 10 -s ./scripts/pipeline.lua http://127.0.0.1:8080/plaintext -- 16
+wrk -c 256 -t 32 -d 15 -s ./scripts/pipeline.lua http://localhost:8080/psql/update?queries=20 -- 16
 ```
 
 *Note you may want to tweak the number of client threads (the `-t` arg) being used based on the specs of your load

+ 26 - 5
frameworks/Java/vertx-web/benchmark_config.json

@@ -41,12 +41,33 @@
       "notes": "",
       "versus": ""
     },
+    "mysql": {
+      "setup_file": "setup",
+      "db_url": "/mysql/db",
+      "query_url": "/mysql/queries?queries=",
+      "fortune_url": "/mysql/fortunes",
+      "update_url": "/mysql/update?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "vertx-web",
+      "language": "Java",
+      "orm": "Raw",
+      "platform": "vertx",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "vertx-web-mysql",
+      "notes": "",
+      "versus": ""
+    },
     "postgres": {
       "setup_file": "setup",
-      "db_url": "/jdbc/db",
-      "query_url": "/jdbc/queries?queries=",
-      "fortune_url": "/jdbc/fortunes",
-      "update_url": "/jdbc/update?queries=",
+      "db_url": "/psql/db",
+      "query_url": "/psql/queries?queries=",
+      "fortune_url": "/psql/fortunes",
+      "update_url": "/psql/update?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",
@@ -58,7 +79,7 @@
       "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "vertx-web-jdbc",
+      "display_name": "vertx-web-postgres",
       "notes": "",
       "versus": ""
     }

+ 2 - 8
frameworks/Java/vertx-web/pom.xml

@@ -12,7 +12,7 @@
   <properties>
     <!-- the main class -->
     <main.verticle>io.vertx.benchmark.App</main.verticle>
-    <vertx.version>3.2.0</vertx.version>
+    <vertx.version>3.2.1</vertx.version>
   </properties>
 
   <dependencies>
@@ -36,7 +36,7 @@
 
     <dependency>
       <groupId>io.vertx</groupId>
-      <artifactId>vertx-jdbc-client</artifactId>
+      <artifactId>vertx-mysql-postgresql-client</artifactId>
       <version>${vertx.version}</version>
     </dependency>
 
@@ -46,12 +46,6 @@
       <version>${vertx.version}</version>
     </dependency>
 
-    <dependency>
-      <groupId>org.postgresql</groupId>
-      <artifactId>postgresql</artifactId>
-      <version>9.4-1206-jdbc42</version>
-    </dependency>
-
   </dependencies>
 
   <build>

+ 1 - 1
frameworks/Java/vertx-web/setup.sh

@@ -6,4 +6,4 @@ fw_depends java maven
 
 mvn clean package
 
-java -Xms2G -Xmx2G -server -XX:+UseNUMA -XX:+UseParallelGC -XX:+AggressiveOpts -Dvertx.disableWebsockets=true -Dvertx.flashPolicyHandler=false -Dvertx.threadChecks=false -Dvertx.disableContextTimings=true -Dvertx.disableTCCL=true -jar target/vertx-benchmark-1.0.0-SNAPSHOT-fat.jar --conf src/main/conf/config.json &
+java -Xms2G -Xmx2G -server -XX:+UseNUMA -XX:+UseParallelGC -XX:+AggressiveOpts -Dvertx.disableWebsockets=true -Dvertx.flashPolicyHandler=false -Dvertx.threadChecks=false -Dvertx.disableContextTimings=true -Dvertx.disableTCCL=true -jar target/vertx-benchmark-1.0.0-SNAPSHOT-fat.jar --instances `grep --count ^processor /proc/cpuinfo` --conf src/main/conf/config.json &

+ 5 - 4
frameworks/Java/vertx-web/src/main/conf/config.json

@@ -2,8 +2,9 @@
   "connection_string": "mongodb://localhost:27017",
   "db_name": "hello_world",
 
-  "url": "jdbc:postgresql://localhost:5432/hello_world",
-  "driver_class": "org.postgresql.Driver",
-  "user": "benchmarkdbuser",
-  "password": "benchmarkdbpass"
+  "host": "localhost",
+  "username": "benchmarkdbuser",
+  "password": "benchmarkdbpass",
+  "database": "hello_world",
+  "maxPoolSize": 32
 }

+ 99 - 32
frameworks/Java/vertx-web/src/main/java/io/vertx/benchmark/App.java

@@ -7,7 +7,9 @@ import io.vertx.core.*;
 import io.vertx.core.http.HttpHeaders;
 import io.vertx.core.json.JsonArray;
 import io.vertx.core.json.JsonObject;
-import io.vertx.ext.jdbc.JDBCClient;
+import io.vertx.ext.asyncsql.AsyncSQLClient;
+import io.vertx.ext.asyncsql.MySQLClient;
+import io.vertx.ext.asyncsql.PostgreSQLClient;
 import io.vertx.ext.mongo.MongoClient;
 import io.vertx.ext.sql.SQLConnection;
 import io.vertx.ext.web.Router;
@@ -168,13 +170,30 @@ public class App extends AbstractVerticle {
   /**
    * JDBC implementation
    */
-  private final class JDBC {
-    private final JDBCClient database;
+  private final class AsyncSQL {
+
+    public static final int MYSQL = 0;
+    public static final int POSTGRES = 1;
+
+    private final AsyncSQLClient database;
+    private final int dbms;
+
     // In order to use a template we first need to create an engine
     private final HandlebarsTemplateEngine engine;
 
-    public JDBC(Vertx vertx, JsonObject config) {
-      this.database = JDBCClient.createShared(vertx, config);
+    public AsyncSQL(Vertx vertx, int driver, JsonObject config) {
+      switch (driver) {
+        case MYSQL:
+          this.database = MySQLClient.createNonShared(vertx, config);
+          this.dbms = MYSQL;
+          break;
+        case POSTGRES:
+          this.database = PostgreSQLClient.createNonShared(vertx, config);
+          this.dbms = POSTGRES;
+          break;
+        default:
+          throw new RuntimeException("Unsupported DB");
+      }
       this.engine = HandlebarsTemplateEngine.create();
     }
 
@@ -216,7 +235,7 @@ public class App extends AbstractVerticle {
 
     public final void queriesHandler(final RoutingContext ctx) {
       final int queries = Helper.getQueries(ctx.request());
-      final World[] worlds = new World[queries];
+      final JsonArray worlds = new JsonArray();
 
       database.getConnection(getConnection -> {
         if (getConnection.failed()) {
@@ -235,7 +254,7 @@ public class App extends AbstractVerticle {
                   .putHeader(HttpHeaders.SERVER, SERVER)
                   .putHeader(HttpHeaders.DATE, date)
                   .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
-                  .end(new JsonArray(Arrays.asList(worlds)).encode());
+                  .end(worlds.encode());
 
               conn.close();
             } else {
@@ -259,7 +278,7 @@ public class App extends AbstractVerticle {
 
                 final JsonArray row = resultSet.get(0);
 
-                worlds[idx] = new World(row.getInteger(0), row.getInteger(1));
+                worlds.add(new World(row.getInteger(0), row.getInteger(1)));
                 self.handle(idx + 1);
               });
             }
@@ -322,7 +341,16 @@ public class App extends AbstractVerticle {
 
     public final void updateHandler(final RoutingContext ctx) {
       final int queries = Helper.getQueries(ctx.request());
-      final World[] worlds = new World[queries];
+      final JsonArray worlds = new JsonArray();
+
+      final StringBuffer batch;
+
+      if (dbms == POSTGRES) {
+        // Postgres can batch queries
+        batch = new StringBuffer();
+      } else {
+        batch = null;
+      }
 
       database.getConnection(getConnection -> {
         if (getConnection.failed()) {
@@ -336,14 +364,34 @@ public class App extends AbstractVerticle {
           @Override
           public void handle(Integer idx) {
             if (idx == queries) {
-              // stop condition
-              ctx.response()
-                  .putHeader(HttpHeaders.SERVER, SERVER)
-                  .putHeader(HttpHeaders.DATE, date)
-                  .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
-                  .end(new JsonArray(Arrays.asList(worlds)).encode());
+              switch (dbms) {
+                case MYSQL:
+                  ctx.response()
+                      .putHeader(HttpHeaders.SERVER, SERVER)
+                      .putHeader(HttpHeaders.DATE, date)
+                      .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
+                      .end(worlds.encode());
 
-              conn.close();
+                  conn.close();
+                  break;
+                case POSTGRES:
+                  // stop condition, first run the batch update
+                  conn.update(batch.toString(), update -> {
+                    if (update.failed()) {
+                      ctx.fail(update.cause());
+                      conn.close();
+                      return;
+                    }
+                    ctx.response()
+                        .putHeader(HttpHeaders.SERVER, SERVER)
+                        .putHeader(HttpHeaders.DATE, date)
+                        .putHeader(HttpHeaders.CONTENT_TYPE, "application/json")
+                        .end(worlds.encode());
+
+                    conn.close();
+                  });
+                  break;
+              }
             } else {
 
               final Handler<Integer> self = this;
@@ -365,17 +413,31 @@ public class App extends AbstractVerticle {
                 }
 
                 final int newRandomNumber = Helper.randomWorld();
-
-                conn.update("UPDATE WORLD SET randomnumber = " + newRandomNumber + " WHERE id = " + id, update -> {
-                  if (update.failed()) {
-                    ctx.fail(update.cause());
-                    conn.close();
-                    return;
-                  }
-
-                  worlds[idx] = new World(id, newRandomNumber);
-                  self.handle(idx + 1);
-                });
+                worlds.add(new World(id, newRandomNumber));
+
+                switch (dbms) {
+                  case MYSQL:
+                    conn.update("UPDATE WORLD SET randomnumber = " + newRandomNumber + " WHERE id = " + id, update -> {
+                      if (update.failed()) {
+                        ctx.fail(update.cause());
+                        conn.close();
+                        return;
+                      }
+
+                      self.handle(idx + 1);
+                    });
+                    break;
+                  case POSTGRES:
+                    batch
+                        .append("UPDATE WORLD SET randomnumber = ")
+                        .append(newRandomNumber)
+                        .append(" WHERE id = ")
+                        .append(id)
+                        .append("; ");
+
+                    self.handle(idx + 1);
+                    break;
+                }
               });
             }
           }
@@ -394,7 +456,8 @@ public class App extends AbstractVerticle {
     vertx.setPeriodic(1000, handler -> date = DateTimeFormatter.RFC_1123_DATE_TIME.format(ZonedDateTime.now()));
 
     final MongoDB mongoDB = new MongoDB(vertx, config());
-    final JDBC jdbc = new JDBC(vertx, config());
+    final AsyncSQL psql = new AsyncSQL(vertx, AsyncSQL.POSTGRES, config());
+    final AsyncSQL mysql = new AsyncSQL(vertx, AsyncSQL.MYSQL, config());
 
     /**
      * This test exercises the framework fundamentals including keep-alive support, request routing, request header
@@ -413,7 +476,8 @@ public class App extends AbstractVerticle {
      * and database connection pool.
      */
     app.get("/mongo/db").handler(mongoDB::dbHandler);
-    app.get("/jdbc/db").handler(jdbc::dbHandler);
+    app.get("/psql/db").handler(psql::dbHandler);
+    app.get("/mysql/db").handler(mysql::dbHandler);
 
     /**
      * This test is a variation of Test #2 and also uses the World table. Multiple rows are fetched to more dramatically
@@ -421,14 +485,16 @@ public class App extends AbstractVerticle {
      * demonstrates all frameworks' convergence toward zero requests-per-second as database activity increases.
      */
     app.get("/mongo/queries").handler(mongoDB::queriesHandler);
-    app.get("/jdbc/queries").handler(jdbc::queriesHandler);
+    app.get("/psql/queries").handler(psql::queriesHandler);
+    app.get("/mysql/queries").handler(mysql::queriesHandler);
 
     /**
      * This test exercises the ORM, database connectivity, dynamic-size collections, sorting, server-side templates,
      * XSS countermeasures, and character encoding.
      */
     app.get("/mongo/fortunes").handler(mongoDB::fortunesHandler);
-    app.get("/jdbc/fortunes").handler(jdbc::fortunesHandler);
+    app.get("/psql/fortunes").handler(psql::fortunesHandler);
+    app.get("/mysql/fortunes").handler(mysql::fortunesHandler);
 
     /**
      * This test is a variation of Test #3 that exercises the ORM's persistence of objects and the database driver's
@@ -436,7 +502,8 @@ public class App extends AbstractVerticle {
      * read-then-write style database operations.
      */
     app.route("/mongo/update").handler(mongoDB::updateHandler);
-    app.route("/jdbc/update").handler(jdbc::updateHandler);
+    app.route("/psql/update").handler(psql::updateHandler);
+    app.route("/mysql/update").handler(mysql::updateHandler);
 
     /**
      * This test is an exercise of the request-routing fundamentals only, designed to demonstrate the capacity of

+ 1 - 1
frameworks/Java/vertx/pom.xml

@@ -8,7 +8,7 @@
 	<properties>
 		<!-- the main class -->
 		<main.class>vertx.WebServer</main.class>
-		<stack.version>3.2.0</stack.version>
+		<stack.version>3.2.1</stack.version>
 	</properties>
 
 	<repositories>

+ 1 - 1
frameworks/Java/wildfly-ee7/benchmark_config.json

@@ -11,7 +11,7 @@
       "update_url": "/wildfly-ee7/rest/updates?queries=",
       "port": 8080,
       "approach": "Realistic",
-      "classification": "Platform",
+      "classification": "Fullstack",
       "database": "MySQL",
       "framework": "EE7",
       "language": "Java",

+ 2 - 1
frameworks/Perl/mojolicious/.gitignore

@@ -1 +1,2 @@
-local
+local
+*.pid

+ 10 - 2
frameworks/Perl/mojolicious/app.pl

@@ -26,7 +26,11 @@ plugin Config => {
 
 helper pg => sub { state $pg = Mojo::Pg->new('postgresql://benchmarkdbuser:benchmarkdbpass@' . shift->config->{database_host} . '/hello_world') };
 
-helper render_json => sub { shift->render( data => encode_json(shift), format => 'json' ) }; 
+helper render_json => sub {
+  my $c = shift;
+  $c->res->headers->content_type('application/json');
+  $c->render( data => encode_json(shift) );
+};
 
 # Routes
 
@@ -51,7 +55,11 @@ get '/updates' => sub {
   $c->helpers->render_query(scalar $c->param('queries'), {update => 1});
 };
 
-get '/plaintext' => sub { shift->render( text => 'Hello, World!' ) };
+get '/plaintext' => sub {
+  my $c = shift;
+  $c->res->headers->content_type('text/plain');
+  $c->render( text => 'Hello, World!' );
+};
 
 # Additional helpers (shared code)
 

+ 35 - 29
frameworks/Perl/mojolicious/cpanfile.snapshot

@@ -1,18 +1,24 @@
 # carton snapshot format: version 1.0
 DISTRIBUTIONS
-  DBD-Pg-3.5.1
-    pathname: T/TU/TURNSTEP/DBD-Pg-3.5.1.tar.gz
+  Canary-Stability-2006
+    pathname: M/ML/MLEHMANN/Canary-Stability-2006.tar.gz
     provides:
-      Bundle::DBD::Pg v3.5.1
-      DBD::Pg v3.5.1
+      Canary::Stability 2006
+    requirements:
+      ExtUtils::MakeMaker 0
+  DBD-Pg-3.5.3
+    pathname: T/TU/TURNSTEP/DBD-Pg-3.5.3.tar.gz
+    provides:
+      Bundle::DBD::Pg v3.5.3
+      DBD::Pg v3.5.3
     requirements:
       DBI 1.614
       ExtUtils::MakeMaker 6.11
       Test::More 0.88
       Time::HiRes 0
       version 0
-  DBI-1.633
-    pathname: T/TI/TIMB/DBI-1.633.tar.gz
+  DBI-1.634
+    pathname: T/TI/TIMB/DBI-1.634.tar.gz
     provides:
       Bundle::DBI 12.008696
       DBD::DBM 0.08
@@ -61,7 +67,7 @@ DISTRIBUTIONS
       DBD::Sponge::dr 12.010003
       DBD::Sponge::st 12.010003
       DBDI 12.015129
-      DBI 1.633
+      DBI 1.634
       DBI::Const::GetInfo::ANSI 2.008697
       DBI::Const::GetInfo::ODBC 2.011374
       DBI::Const::GetInfoReturn 2.008697
@@ -102,23 +108,24 @@ DISTRIBUTIONS
       DBI::SQL::Nano::Table_ 1.015544
       DBI::Util::CacheMemory 0.010315
       DBI::Util::_accessor 0.009479
-      DBI::common 1.633
+      DBI::common 1.634
     requirements:
       ExtUtils::MakeMaker 6.48
       Test::Simple 0.90
       perl 5.008
-  EV-4.18
-    pathname: M/ML/MLEHMANN/EV-4.18.tar.gz
+  EV-4.22
+    pathname: M/ML/MLEHMANN/EV-4.22.tar.gz
     provides:
-      EV 4.18
+      EV 4.22
       EV::MakeMaker undef
     requirements:
-      ExtUtils::MakeMaker 0
+      Canary::Stability 0
+      ExtUtils::MakeMaker 6.52
       common::sense 0
-  IO-Socket-IP-0.36
-    pathname: P/PE/PEVANS/IO-Socket-IP-0.36.tar.gz
+  IO-Socket-IP-0.37
+    pathname: P/PE/PEVANS/IO-Socket-IP-0.37.tar.gz
     provides:
-      IO::Socket::IP 0.36
+      IO::Socket::IP 0.37
     requirements:
       IO::Socket 0
       Socket 1.97
@@ -131,22 +138,21 @@ DISTRIBUTIONS
       ExtUtils::MakeMaker 0
       Types::Serialiser 0
       common::sense 0
-  Mojo-Pg-1.14
-    pathname: S/SR/SRI/Mojo-Pg-1.14.tar.gz
+  Mojo-Pg-2.23
+    pathname: S/SR/SRI/Mojo-Pg-2.23.tar.gz
     provides:
-      Mojo::Pg 1.14
+      Mojo::Pg 2.23
       Mojo::Pg::Database undef
       Mojo::Pg::Migrations undef
       Mojo::Pg::PubSub undef
       Mojo::Pg::Results undef
       Mojo::Pg::Transaction undef
     requirements:
-      DBD::Pg 0
+      DBD::Pg 3.005001
       ExtUtils::MakeMaker 0
       Mojolicious 6.0
-      perl 5.010001
-  Mojolicious-6.02
-    pathname: S/SR/SRI/Mojolicious-6.02.tar.gz
+  Mojolicious-6.48
+    pathname: S/SR/SRI/Mojolicious-6.48.tar.gz
     provides:
       Mojo undef
       Mojo::Asset undef
@@ -178,7 +184,6 @@ DISTRIBUTIONS
       Mojo::IOLoop::Stream undef
       Mojo::JSON undef
       Mojo::JSON::Pointer undef
-      Mojo::JSON::_Bool undef
       Mojo::Loader undef
       Mojo::Log undef
       Mojo::Message undef
@@ -209,7 +214,8 @@ DISTRIBUTIONS
       Mojo::UserAgent::Server undef
       Mojo::UserAgent::Transactor undef
       Mojo::Util undef
-      Mojolicious 6.02
+      Mojo::WebSocket undef
+      Mojolicious 6.48
       Mojolicious::Command undef
       Mojolicious::Command::cgi undef
       Mojolicious::Command::cpanify undef
@@ -257,10 +263,10 @@ DISTRIBUTIONS
       ojo undef
     requirements:
       ExtUtils::MakeMaker 0
-      IO::Socket::IP 0.26
+      IO::Socket::IP 0.37
+      JSON::PP 2.27103
       Pod::Simple 3.09
       Time::Local 1.2
-      perl 5.010001
   Types-Serialiser-1.0
     pathname: M/ML/MLEHMANN/Types-Serialiser-1.0.tar.gz
     provides:
@@ -271,9 +277,9 @@ DISTRIBUTIONS
     requirements:
       ExtUtils::MakeMaker 0
       common::sense 0
-  common-sense-3.73
-    pathname: M/ML/MLEHMANN/common-sense-3.73.tar.gz
+  common-sense-3.74
+    pathname: M/ML/MLEHMANN/common-sense-3.74.tar.gz
     provides:
-      common::sense 3.73
+      common::sense 3.74
     requirements:
       ExtUtils::MakeMaker 0

+ 8 - 0
frameworks/Python/asyncio/aiohttp.web/etc/hello/main/main.yaml

@@ -8,6 +8,14 @@ engines:
     password: benchmarkdbpass
     minsize: 22
     maxsize: 22
+  mysql:
+    host: 127.0.0.1
+    port: 3306
+    db: hello_world
+    user: benchmarkdbuser
+    pwd: benchmarkdbpass
+    minsize: 22
+    maxsize: 22
   redis:
     host: 127.0.0.1
     port: 6379

+ 23 - 0
frameworks/Python/asyncio/aiohttp.web/hello/__init__.py

@@ -9,6 +9,7 @@ import asyncio_redis
 from asyncio_redis.protocol import HiRedisProtocol
 import aiohttp.web
 import aiohttp_jinja2
+import aiomysql
 import api_hour
 
 from . import endpoints
@@ -27,12 +28,16 @@ class Container(api_hour.Container):
         self.servers['http'].router.add_route('GET', '/json', endpoints.world.json)
         self.servers['http'].router.add_route('GET', '/db', endpoints.world.db)
         self.servers['http'].router.add_route('GET', '/db_redis', endpoints.world.db_redis)
+        self.servers['http'].router.add_route('GET', '/db_mysql', endpoints.world.db_mysql)
         self.servers['http'].router.add_route('GET', '/queries', endpoints.world.queries)
         self.servers['http'].router.add_route('GET', '/queries_redis', endpoints.world.queries_redis)
+        self.servers['http'].router.add_route('GET', '/queries_mysql', endpoints.world.queries_mysql)
         self.servers['http'].router.add_route('GET', '/fortunes', endpoints.world.fortunes)
         self.servers['http'].router.add_route('GET', '/fortunes_redis', endpoints.world.fortunes_redis)
+        self.servers['http'].router.add_route('GET', '/fortunes_mysql', endpoints.world.fortunes_mysql)
         self.servers['http'].router.add_route('GET', '/updates', endpoints.world.updates)
         self.servers['http'].router.add_route('GET', '/updates_redis', endpoints.world.updates_redis)
+        self.servers['http'].router.add_route('GET', '/updates_mysql', endpoints.world.updates_mysql)
         self.servers['http'].router.add_route('GET', '/plaintext', endpoints.world.plaintext)
 
     def make_servers(self):
@@ -56,6 +61,18 @@ class Container(api_hour.Container):
                                                                      minsize=int(self.config['engines']['pg']['minsize']),
                                                                      maxsize=int(self.config['engines']['pg']['maxsize']),
                                                                      loop=self.loop))
+        self.engines['mysql'] = self.loop.create_task(aiomysql.create_pool(
+                host=self.config['engines']['mysql']['host'],
+                port=self.config['engines']['mysql']['port'],
+                user=self.config['engines']['mysql']['user'],
+                password=self.config['engines']['mysql']['pwd'],
+                db=self.config['engines']['mysql']['db'],
+                minsize=int(self.config['engines']['mysql']['minsize']),
+                maxsize=int(self.config['engines']['mysql']['maxsize']),
+                cursorclass=aiomysql.DictCursor,
+                charset='utf8',
+                use_unicode=True,
+                loop=self.loop))
         yield from asyncio.wait([self.engines['pg']], return_when=asyncio.ALL_COMPLETED)
         self.engines['redis'] = yield from asyncio_redis.Pool.create(host=self.config['engines']['redis']['host'],
                                                                      port=self.config['engines']['redis']['port'],
@@ -74,6 +91,12 @@ class Container(api_hour.Container):
                 yield from self.engines['pg'].result().wait_closed()
             else:
                 yield from self.engines['pg'].cancel()
+        if 'mysql' in self.engines:
+            if self.engines['mysql'].done():
+                self.engines['mysql'].result().close()
+                yield from self.engines['mysql'].result().wait_closed()
+            else:
+                yield from self.engines['mysql'].cancel()
         if 'redis' in self.engines:
             self.engines['redis'].close()
             yield from asyncio.sleep(1) # wait redis close connection

+ 33 - 1
frameworks/Python/asyncio/aiohttp.web/hello/endpoints/world.py

@@ -7,7 +7,7 @@ import aiohttp_jinja2
 
 from ..services import queries_number
 from ..services.world import get_random_record, get_random_records, update_random_records, get_fortunes
-from ..services import redis
+from ..services import redis, mysql
 
 LOG = logging.getLogger(__name__)
 
@@ -30,6 +30,13 @@ def db_redis(request):
 
     return JSON((yield from redis.get_random_record(container)))
 
[email protected]
+def db_mysql(request):
+    """Test type 2: Single database query"""
+    container = request.app.ah_container
+
+    return JSON((yield from mysql.get_random_record(container)))
+
 @asyncio.coroutine
 def queries(request):
     """Test type 3: Multiple database queries"""
@@ -46,6 +53,14 @@ def queries_redis(request):
 
     return JSON((yield from redis.get_random_records(container, limit)))
 
[email protected]
+def queries_mysql(request):
+    """Test type 3: Multiple database queries"""
+    container = request.app.ah_container
+    limit = queries_number(request.GET.get('queries', 1))
+
+    return JSON((yield from mysql.get_random_records(container, limit)))
+
 @asyncio.coroutine
 def fortunes(request):
     """Test type 4: Fortunes"""
@@ -64,6 +79,15 @@ def fortunes_redis(request):
                                           request,
                                           {'fortunes': (yield from redis.get_fortunes(container))})
 
[email protected]
+def fortunes_mysql(request):
+    """Test type 4: Fortunes"""
+    container = request.app.ah_container
+
+    return aiohttp_jinja2.render_template('fortunes.html.j2',
+                                          request,
+                                          {'fortunes': (yield from mysql.get_fortunes(container))})
+
 @asyncio.coroutine
 def updates(request):
     """Test type 5: Database updates"""
@@ -80,6 +104,14 @@ def updates_redis(request):
 
     return JSON((yield from redis.update_random_records(container, limit)))
 
[email protected]
+def updates_mysql(request):
+    """Test type 5: Database updates"""
+    container = request.app.ah_container
+    limit = queries_number(request.GET.get('queries', 1))
+
+    return JSON((yield from mysql.update_random_records(container, limit)))
+
 @asyncio.coroutine
 def plaintext(request):
     """Test type 6: Plaintext"""

+ 56 - 0
frameworks/Python/asyncio/aiohttp.web/hello/services/mysql.py

@@ -0,0 +1,56 @@
+import asyncio
+from random import randint
+from operator import itemgetter
+
+
[email protected]
+def get_random_record(container):
+    with (yield from container.engines['mysql'].result()) as mysql_conn:
+        cur = yield from mysql_conn.cursor()
+        yield from cur.execute('SELECT id AS "Id", randomnumber AS "RandomNumber" FROM world WHERE id=%(idx)s LIMIT 1',
+                               {'idx': randint(1, 10000)})
+        world = yield from cur.fetchone()
+    return world
+
+
[email protected]
+def get_random_records(container, limit):
+    results = []
+    with (yield from container.engines['mysql'].result()) as mysql_conn:
+        cur = yield from mysql_conn.cursor()
+        for i in range(limit):
+            yield from cur.execute('SELECT id AS "Id", randomnumber AS "RandomNumber" FROM world WHERE id=%(idx)s LIMIT 1',
+                                   {'idx': randint(1, 10000)})
+            results.append((yield from cur.fetchone()))
+
+    return results
+
+
[email protected]
+def update_random_records(container, limit):
+    results = []
+
+    with (yield from container.engines['mysql'].result()) as mysql_conn:
+        cur = yield from mysql_conn.cursor()
+        for i in range(limit):
+            yield from cur.execute('SELECT id AS "Id", randomnumber AS "RandomNumber" FROM world WHERE id=%(idx)s LIMIT 1',
+                                   {'idx': randint(1, 10000)})
+            world = yield from cur.fetchone()
+            yield from cur.execute('UPDATE world SET randomnumber=%(random_number)s WHERE id=%(idx)s',
+                                   {'random_number': randint(1, 10000), 'idx': world['Id']})
+            results.append(world)
+    return results
+
+
[email protected]
+def get_fortunes(container):
+    with (yield from container.engines['mysql'].result()) as mysql_conn:
+        cur = yield from mysql_conn.cursor()
+        yield from cur.execute('SELECT * FROM fortune')
+        fortunes = yield from cur.fetchall()
+
+    fortunes.append({'id': 0, 'message': 'Additional fortune added at request time.'})
+
+    fortunes.sort(key=itemgetter('message'))
+
+    return fortunes

+ 20 - 0
frameworks/Python/asyncio/benchmark_config.json

@@ -43,6 +43,26 @@
       "display_name": "API-Hour+aiohttp.web+redis",
       "notes": "Python 3 + API-Hour + AsyncIO + aiohttp.web + Redis"
     },
+    "mysql": {
+      "setup_file": "aiohttp.web/setup",
+      "db_url": "/db_mysql",
+      "query_url": "/queries_mysql?queries=",
+      "fortune_url": "/fortunes_mysql",
+      "update_url": "/updates_mysql?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "aiohttp.web",
+      "language": "Python",
+      "orm": "Raw",
+      "platform": "API-Hour",
+      "webserver": "Gunicorn",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "API-Hour+aiohttp.web+mysql",
+      "notes": "Python 3 + API-Hour + AsyncIO + aiohttp.web + MySQL"
+    },
     "json": {
       "setup_file": "yocto_http/setup",
       "json_url": "/json",

+ 2 - 0
frameworks/Python/asyncio/requirements.txt

@@ -16,3 +16,5 @@ requests-futures==0.9.5
 setproctitle==1.1.8
 six==1.9.0
 ujson==1.33
+aiomysql==0.0.7
+PyMySQL==0.6.7

+ 1 - 2
frameworks/Rust/hyper/Cargo.toml

@@ -4,5 +4,4 @@ version = "0.1.0"
 authors = ["Steve Klabnik <[email protected]>"]
 
 [dependencies]
-
-hyper="0.5.2"
+hyper="0.7.2"

+ 13 - 13
frameworks/Rust/hyper/src/main.rs

@@ -1,24 +1,24 @@
 extern crate hyper;
 
 use hyper::server::{Server, Request, Response};
-use hyper::status::StatusCode;
 use hyper::uri::RequestUri;
 use hyper::header::ContentType;
-use hyper::header::ContentLength;
 use hyper::header;
 
-const HELLO_WORLD: &'static [u8; 14] = b"Hello, World!\n";
+const HELLO_WORLD: &'static [u8; 13] = b"Hello, World!";
 
 fn main() {
-    Server::http(|req: Request, mut res: Response| {
-        match (req.method, req.uri) {
-            (hyper::Get, RequestUri::AbsolutePath(ref path)) if path == "/plaintext" => {
-                res.headers_mut().set(ContentType::plaintext());
-                res.headers_mut().set(header::Server("Hyper".to_owned()));
+    Server::http("0.0.0.0:8080").unwrap().handle(handler).unwrap();
+}
+
+fn handler(req: Request, mut res: Response) {
+    match (req.method, req.uri) {
+        (hyper::Get, RequestUri::AbsolutePath(ref path)) if path == "/plaintext" => {
+            res.headers_mut().set(ContentType("text/plain".parse().unwrap()));
+            res.headers_mut().set(header::Server("Hyper".to_owned()));
 
-                res.send(HELLO_WORLD).unwrap();
-            }
-            _ => (),
-        };
-    }).listen("0.0.0.0:8080").unwrap();
+            res.send(HELLO_WORLD).unwrap();
+        }
+        _ => (),
+    }
 }

+ 3 - 3
frameworks/Rust/iron/Cargo.toml

@@ -4,6 +4,6 @@ name = "iron"
 version = "0.0.1"
 
 [dependencies]
-rustc-serialize = "0.3"
-iron = "0.1.18"
-router = "0.0.10"
+rustc-serialize = "0.3.18"
+iron = "0.2.6"
+router = "0.1.0"

+ 1 - 1
frameworks/Rust/iron/setup.sh

@@ -2,6 +2,6 @@
 
 fw_depends rust
 
-rm -rf target/
+cargo clean
 cargo build --release
 ./target/release/iron &

+ 14 - 10
frameworks/Rust/iron/src/main.rs

@@ -4,8 +4,11 @@ extern crate rustc_serialize;
 
 use iron::{Iron, Request, Response, IronResult};
 use iron::status;
-use router::{Router};
+use router::Router;
 use rustc_serialize::json;
+use iron::mime::Mime;
+use iron::headers::Server;
+use iron::modifiers::Header;
 
 #[derive(RustcDecodable, RustcEncodable)]
 struct Message {
@@ -14,19 +17,20 @@ struct Message {
 
 fn main() {
     let mut router = Router::new();
-    router.get("/json", jsonHandler);
-    router.get("/plaintext", plaintextHandler);
+    router.get("/json", json_handler);
+    router.get("/plaintext", plaintext_handler);
 
     Iron::new(router).http("0.0.0.0:8080").unwrap();
 }
 
-fn jsonHandler(req: &mut Request) -> IronResult<Response> {
-    let message: Message = Message{
-        message: "Hello, World!".to_string(),
-    };
-    Ok(Response::with((status::Ok, json::encode(&message).unwrap())))
+fn json_handler(_: &mut Request) -> IronResult<Response> {
+    let message: Message = Message { message: "Hello, World!".to_string() };
+    let mime: Mime = "application/json".parse().unwrap();
+    let server = Header(Server(String::from("Iron")));
+    Ok(Response::with((status::Ok, json::encode(&message).unwrap(), mime, server)))
 }
 
-fn plaintextHandler(req: &mut Request) -> IronResult<Response> {
-    Ok(Response::with((status::Ok, "Hello, World!")))
+fn plaintext_handler(_: &mut Request) -> IronResult<Response> {
+    let server = Header(Server(String::from("Iron")));
+    Ok(Response::with((status::Ok, "Hello, World!", server)))
 }

+ 2 - 2
frameworks/Rust/nickel/Cargo.toml

@@ -4,6 +4,6 @@ name = "nickel"
 version = "0.0.1"
 
 [dependencies]
-rustc-serialize = "0.3"
-nickel = "0.5.0"
+rustc-serialize = "0.3.18"
+nickel = "0.7.3"
 nickel_macros = "0.1.0"

+ 1 - 1
frameworks/Rust/nickel/setup.sh

@@ -2,6 +2,6 @@
 
 fw_depends rust
 
-rm -rf target/
+cargo clean
 cargo build --release
 ./target/release/nickel &

+ 7 - 4
frameworks/Rust/nickel/src/main.rs

@@ -1,7 +1,8 @@
-#[macro_use] extern crate nickel;
+#[macro_use]
+extern crate nickel;
 extern crate rustc_serialize;
 
-use nickel::{ Nickel, HttpRouter, MediaType };
+use nickel::{Nickel, HttpRouter, MediaType};
 use rustc_serialize::json;
 
 #[derive(RustcDecodable, RustcEncodable)]
@@ -13,7 +14,8 @@ fn main() {
     let mut server = Nickel::new();
     let mut router = Nickel::router();
 
-    router.get("/json", middleware!{ |_, mut response|
+    router.get("/json",
+               middleware!{ |_, mut response|
         response.set(MediaType::Json);
         let message: Message = Message{
             message: "Hello, World!".to_string(),
@@ -21,7 +23,8 @@ fn main() {
         json::encode(&message).unwrap()
     });
 
-    router.get("/plaintext", middleware! { |_, mut response|
+    router.get("/plaintext",
+               middleware! { |_, mut response|
         response.set(MediaType::Txt);
         "Hello, World!"
     });

+ 2 - 3
frameworks/Scala/akka-http/build.sbt

@@ -9,9 +9,8 @@ scalaVersion := "2.11.7"
 resolvers += "Akka Snapshot Repository" at "http://repo.akka.io/snapshots/"
 
 libraryDependencies ++= Seq(
-  "com.typesafe.akka" %% "akka-http-core-experimental" % "2.0-M2",
-  "com.typesafe.akka" %% "akka-http-experimental" % "2.0-M2",
-  "com.typesafe.akka" %% "akka-http-spray-json-experimental" % "2.0-M2",
+  "com.typesafe.akka" %% "akka-http-experimental" % "2.4.2",
+  "com.typesafe.akka" %% "akka-http-spray-json-experimental" % "2.4.2",
   "mysql" % "mysql-connector-java" % "5.1.35",
   "org.apache.commons" % "commons-dbcp2" % "2.1",
   "org.scalatra.scalate" %% "scalate-core" % "1.7.0",

+ 1 - 1
frameworks/Scala/akka-http/project/build.properties

@@ -1 +1 @@
-sbt.version=0.13.8
+sbt.version=0.13.11

+ 3 - 11
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/Bootstrap.scala

@@ -2,9 +2,8 @@ package com.typesafe.akka.http.benchmark
 
 import akka.actor.ActorSystem
 import akka.http.scaladsl.Http
-import akka.http.scaladsl.server.{Route, RoutingLog, RoutingSettings}
+import akka.http.scaladsl.server.Route
 import akka.stream.ActorMaterializer
-import akka.stream.scaladsl.Sink._
 import com.typesafe.config.Config
 
 trait Bootstrap {
@@ -23,15 +22,8 @@ class BenchmarkBootstrap(components: {
 
   override def run(): Unit = {
 
-    implicit val routingLog = RoutingLog(system.log)
+    implicit val system = ActorSystem()
     implicit val materializer = ActorMaterializer()
-    implicit val settings = RoutingSettings.default(system)
-    val handler = Route.asyncHandler(components.route)
-    val server = Http(components.system).bind(config.getString("akka.http.benchmark.host"), config.getInt("akka.http.benchmark.port"))
-    server.to {
-      foreach { connection =>
-        connection.handleWithAsyncHandler(handler)
-      }
-    }.run()
+    Http().bindAndHandle(components.route, config.getString("akka.http.benchmark.host"), config.getInt("akka.http.benchmark.port"))
   }
 }

+ 1 - 1
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/DbHandler.scala

@@ -35,7 +35,7 @@ class DbHandler(components: {
   def response = {
     val id = randomGenerator.next
     dataStore.findOne(id).map {
-      record => new HttpResponse(StatusCodes.OK, entity = HttpEntity(record.toResponse.toJson.toString()).withContentType(`application/json`.withCharset(`UTF-8`)))
+      record => new HttpResponse(StatusCodes.OK, entity = HttpEntity(record.toResponse.toJson.toString()).withContentType(`application/json`))
     }
   }
 

+ 1 - 1
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/JsonHandler.scala

@@ -20,7 +20,7 @@ class JsonHandler(components: {
   }
 
   def response = {
-    new HttpResponse(StatusCodes.OK, entity = HttpEntity(Response("Hello, World!").toJson.toString()).withContentType(`application/json`.withCharset(`UTF-8`)))
+    new HttpResponse(StatusCodes.OK, entity = HttpEntity(Response("Hello, World!").toJson.toString()).withContentType(`application/json`))
   }
 }
 

+ 1 - 1
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/QueriesHandler.scala

@@ -54,7 +54,7 @@ class QueriesHandler(components: {
         id => dataStore.findOne(id)
       }
     }.map {
-      worlds => new HttpResponse(StatusCodes.OK, entity = HttpEntity(worlds.toList.map(_.toResponse).toJson.toString()).withContentType(`application/json`.withCharset(`UTF-8`)))
+      worlds => new HttpResponse(StatusCodes.OK, entity = HttpEntity(worlds.toList.map(_.toResponse).toJson.toString()).withContentType(`application/json`))
     }
 
   }

+ 1 - 1
frameworks/Scala/akka-http/src/main/scala/com/typesafe/akka/http/benchmark/handlers/UpdatesHandler.scala

@@ -52,7 +52,7 @@ class UpdatesHandler(components: {
     }.flatMap {
       worlds => Future.sequence(worlds.map(world => dataStore.updateOne(world.id, world.randomNumber).map(_ => world)))
     }.map {
-      worlds => new HttpResponse(StatusCodes.OK, entity = HttpEntity(worlds.map(_.toResponse).toJson.toString()).withContentType(`application/json`.withCharset(`UTF-8`)))
+      worlds => new HttpResponse(StatusCodes.OK, entity = HttpEntity(worlds.map(_.toResponse).toJson.toString()).withContentType(`application/json`))
     }
   }
 }

BIN
frameworks/Scala/finagle/.cache


+ 0 - 34
frameworks/Scala/finagle/.classpath

@@ -1,34 +0,0 @@
-<classpath>
-  <classpathentry output="target/scala-2.10/classes" path="src/main/scala" kind="src"></classpathentry>
-  <classpathentry output="target/scala-2.10/classes" path="src/main/java" kind="src"></classpathentry>
-  <classpathentry output="target/scala-2.10/test-classes" path="src/test/scala" kind="src"></classpathentry>
-  <classpathentry output="target/scala-2.10/test-classes" path="src/test/java" kind="src"></classpathentry>
-  <classpathentry kind="con" path="org.scala-ide.sdt.launching.SCALA_CONTAINER"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/finagle-http_2.10/jars/finagle-http_2.10-6.2.1.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/finagle-core_2.10/jars/finagle-core_2.10-6.2.1.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/io.netty/netty/bundles/netty-3.5.12.Final.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-core_2.10/jars/util-core_2.10-6.2.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-collection_2.10/jars/util-collection_2.10-6.2.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/commons-collections/commons-collections/jars/commons-collections-3.2.1.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-hashing_2.10/jars/util-hashing_2.10-6.2.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-jvm_2.10/jars/util-jvm_2.10-6.2.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-logging_2.10/jars/util-logging_2.10-6.2.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-app_2.10/jars/util-app_2.10-6.2.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.twitter/util-codec_2.10/jars/util-codec_2.10-6.2.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/commons-codec/commons-codec/jars/commons-codec-1.5.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/commons-lang/commons-lang/jars/commons-lang-2.6.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.module/jackson-module-scala_2.10/jars/jackson-module-scala_2.10-2.1.3.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.core/jackson-core/jars/jackson-core-2.1.2.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.core/jackson-annotations/jars/jackson-annotations-2.1.2.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.fasterxml.jackson.core/jackson-databind/jars/jackson-databind-2.1.2.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.thoughtworks.paranamer/paranamer/jars/paranamer-2.3.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.google.guava/guava/jars/guava-13.0.1.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/org.scala-lang/scala-reflect/jars/scala-reflect-2.10.0.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/com.typesafe.slick/slick_2.10/jars/slick_2.10-1.0.0.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/org.slf4j/slf4j-api/jars/slf4j-api-1.6.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/mysql/mysql-connector-java/jars/mysql-connector-java-5.1.24.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/commons-dbcp/commons-dbcp/jars/commons-dbcp-1.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="/home/dknapp/.ivy2/cache/commons-pool/commons-pool/jars/commons-pool-1.5.4.jar" kind="lib"></classpathentry>
-  <classpathentry path="org.eclipse.jdt.launching.JRE_CONTAINER" kind="con"></classpathentry>
-  <classpathentry path="bin" kind="output"></classpathentry>
-</classpath>

+ 0 - 12
frameworks/Scala/finagle/.project

@@ -1,12 +0,0 @@
-<projectDescription>
-  <name>finagle</name>
-  <buildSpec>
-    <buildCommand>
-      <name>org.scala-ide.sdt.core.scalabuilder</name>
-    </buildCommand>
-  </buildSpec>
-  <natures>
-    <nature>org.scala-ide.sdt.core.scalanature</nature>
-    <nature>org.eclipse.jdt.core.javanature</nature>
-  </natures>
-</projectDescription>

+ 3 - 2
frameworks/Scala/finagle/benchmark_config.json

@@ -4,13 +4,14 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",
-      "database": "MySQL",
+      "database": "None",
       "framework": "finagle",
       "language": "Scala",
-      "orm": "Micro",
+      "orm": "Raw",
       "platform": "Netty",
       "webserver": "None",
       "os": "Linux",

+ 3 - 7
frameworks/Scala/finagle/build.sbt

@@ -1,14 +1,10 @@
 name := "finagle"
 
-organization := "com.falmarri"
-
 scalaVersion := "2.11.7"
 
 version := "1.0"
 
 libraryDependencies ++= Seq(
-                "com.twitter" %% "finagle-http" % "6.+",
-                "com.twitter" %% "finagle-mysql" % "6.+",
-                "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.+",
-				"com.fasterxml.jackson.core" % "jackson-databind" % "2.3.0"
-            )
+  "com.twitter" %% "finagle-http" % "6.33.0",
+  "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.5.3"
+)

+ 1 - 1
frameworks/Scala/finagle/setup.sh

@@ -4,4 +4,4 @@ fw_depends java sbt
 
 sbt update compile -batch
 
-sbt -Ddb.host=${DBHOST} run &
+sbt run &

+ 2 - 2
frameworks/Scala/finagle/source_code

@@ -1,2 +1,2 @@
-finagle/src/main/scala/com/falmarri/finagle/
-finagle/src/main/scala/com/falmarri/finagle/Finagle.scala
+finagle/src/main/scala/
+finagle/src/main/scala/Main.scala

+ 52 - 0
frameworks/Scala/finagle/src/main/scala/Main.scala

@@ -0,0 +1,52 @@
+import java.text.{DateFormat, SimpleDateFormat}
+import java.util.Date
+
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.module.scala.DefaultScalaModule
+import com.twitter.finagle.{Service, SimpleFilter, Http}
+import com.twitter.finagle.stats.NullStatsReceiver
+import com.twitter.finagle.tracing.NullTracer
+import com.twitter.finagle.http.{Request, Response, HttpMuxer}
+import com.twitter.util.{Await, Future}
+import com.twitter.io.Buf
+
+object Main extends App {
+
+  val mapper: ObjectMapper = new ObjectMapper().registerModule(DefaultScalaModule)
+  val dateFormat: DateFormat = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z")
+
+  val helloWorld: Buf = Buf.Utf8("Hello, World!")
+
+  val muxer: HttpMuxer = new HttpMuxer()
+    .withHandler("/json", Service.mk { req: Request =>
+      val rep = Response()
+      rep.content = Buf.Utf8(mapper.writeValueAsString(Map("message" -> "Hello, World!")))
+      rep.contentType = "application/json"
+
+      Future.value(rep)
+    })
+    .withHandler("/plaintext", Service.mk { req: Request => 
+      val rep = Response()
+      rep.content = helloWorld
+      rep.contentType = "text/plain"
+
+      Future.value(rep)
+    })
+
+  val serverAndDate: SimpleFilter[Request, Response] = new SimpleFilter[Request, Response] {
+    def apply(req: Request, s: Service[Request, Response]): Future[Response] =
+      s(req).map { rep =>
+        rep.headerMap.set("Server", "Finagle")
+        rep.headerMap.set("Date", dateFormat.format(new Date()))
+
+        rep
+      }
+  }
+
+  Await.ready(Http.server
+    .withCompressionLevel(0)
+    .withStatsReceiver(NullStatsReceiver)
+    .withTracer(NullTracer)
+    .serve(":8080", serverAndDate.andThen(muxer))
+  )
+}

+ 0 - 105
frameworks/Scala/finagle/src/main/scala/com/falmarri/finagle/Finagle.scala

@@ -1,105 +0,0 @@
-package com.falmarri.finagle
-
-import scala.util.Random
-import scala.collection.immutable.StringOps
-import com.fasterxml.jackson.databind.ObjectMapper
-import com.fasterxml.jackson.module.scala.DefaultScalaModule
-import com.twitter.finagle.Service
-import com.twitter.finagle.exp.Mysql
-import com.twitter.finagle.exp.mysql._
-import org.jboss.netty.handler.codec.http._
-import org.jboss.netty.handler.codec.http.HttpResponseStatus._
-import org.jboss.netty.handler.codec.http.HttpVersion.HTTP_1_1
-import org.jboss.netty.buffer.ChannelBuffers.wrappedBuffer
-import com.twitter.util.Future
-import java.net.InetSocketAddress
-import com.twitter.finagle.builder.{Server, ServerBuilder}
-import com.twitter.finagle.http.{Http,HttpMuxer}
-
-object FinagleBenchmark extends App {
-  val maxConnections = 256
-
-  //val mysql = new Client(ClientBuilder()
-  //  .codec(new MySQL("benchmarkdbuser", "benchmarkdbpass", Some("hello_world")))
-  //  .hosts(new InetSocketAddress(System.getProperty("db.host", "localhost"), 3306))
-  //  .hostConnectionLimit(maxConnections)
-  //  .buildFactory())
-
-  val username = "benchmarkdbuser"
-  val password = "benchmarkdbpass"
-  val db = "hello_world"
-  val host = System.getProperty("db.host", "localhost")
-
-  val mysql = Mysql
-      .withCredentials(username, password)
-      .withDatabase(db)
-      .newRichClient(host + ":3306")
-
-  val mapper = new ObjectMapper()
-  mapper.registerModule(DefaultScalaModule)
-
-  def getValue(row: Row, name: String): Any = row(name) match {
-    case Some(IntValue(v)) => v
-    case _ => throw new Exception("couldn't get value for %s".format(name))
-  }
-
-  def rowToMap(row: Row) = {
-    Map(
-      "id" -> getValue(row, "id"),
-      "randomNumber" -> getValue(row, "randomNumber")
-    )
-  }
-
-  def serialize(result: Any): Array[Byte] =
-    mapper.writeValueAsBytes(result)
-
-  def createResponse(req: HttpRequest, bytes: Array[Byte]) = {
-    val body = wrappedBuffer(bytes)
-    val resp = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK)
-    //resp.setContentTypeJson
-    resp.setContent(body)
-    //resp.contentLength = body.readableBytes
-    resp
-  }
-
-  val muxService = new HttpMuxer()
-    .withHandler("/json", new Service[HttpRequest, HttpResponse] {
-      def apply(req: HttpRequest): Future[HttpResponse] =
-        Future.value(createResponse(req, serialize(Map("message" -> "Hello, World!"))))
-    })
-  /*
-    .withHandler("/db", new Service[HttpRequest, HttpResponse] {
-      val rand = new Random()
-      val sql = "SELECT * FROM world WHERE id = "
-
-      def apply(req: HttpRequest): Future[HttpResponse] = {
-        //val n = req.params.getIntOrElse("queries", 1)
-        val decoder = new QueryStringDecoder(req.getUri())
-        val n = {
-          val queries = decoder.getParameters().get("queries")
-          if(queries == null) {
-            1
-          }
-          else {
-            queries.get(0).toInt
-          }
-        }
-
-        val qs = (0 until n) map { i =>
-          mysql.select(sql + rand.nextInt(10000))(rowToMap)
-        }
-
-        Future.collect(qs) map { results =>
-          createResponse(req, serialize(results.flatten))
-        }
-      }
-    })
-   */
-
-  //Http.serve(new InetSocketAddress(8080), HttpMuxer)
-  val server: Server = ServerBuilder()
-    .codec(Http())
-    .bindTo(new InetSocketAddress(8080))
-    .name("HttpServer")
-    .build(muxService)
-}

+ 5 - 5
frameworks/Scala/finch/build.sbt

@@ -9,11 +9,11 @@ com.github.retronym.SbtOneJar.oneJarSettings
 mainClass in (Compile, run) := Some("WebServer")
 
 libraryDependencies ++= Seq(
-  "com.github.finagle" %% "finch-core" % "0.8.0",
-  "com.github.finagle" %% "finch-circe" % "0.8.0",
-  "io.circe" %% "circe-core" % "0.1.1",
-  "io.circe" %% "circe-generic" % "0.1.1",
-  "io.circe" %% "circe-jawn" % "0.1.1"
+  "com.github.finagle" %% "finch-core" % "0.10.0",
+  "com.github.finagle" %% "finch-circe" % "0.10.0"  ,
+  "io.circe" %% "circe-core" % "0.3.0",
+  "io.circe" %% "circe-generic" % "0.3.0",
+  "io.circe" %% "circe-jawn" % "0.3.0"
 )
 
 resolvers += Resolver.sonatypeRepo("snapshots")

+ 20 - 16
frameworks/Scala/finch/src/main/scala/WebServer.scala

@@ -1,38 +1,42 @@
 import java.net.InetSocketAddress
+import java.text.{DateFormat, SimpleDateFormat}
+import java.util.Date
 
 import io.finch._
-import io.finch.route._
-import io.finch.response._
 
 import com.twitter.finagle.Service
-import com.twitter.finagle.Httpx
-import com.twitter.finagle.httpx.{Response, Request}
-
+import com.twitter.finagle.Http
+import com.twitter.finagle.stats.NullStatsReceiver
+import com.twitter.finagle.tracing.NullTracer
 import com.twitter.util.Await
 
 import io.circe._
 import io.circe.generic.auto._
 import io.circe.jawn._
 import io.circe.syntax._
-import io.finch.response.EncodeResponse
 import io.circe.{Decoder, Encoder, Json}
 
 object WebServer extends App {
+  private val dateFormat: DateFormat = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z")
 
+  import io.finch.circe._
   val json = get("json") {
-    import io.finch.circe._
-
-    case class Message(message: String)
-    Ok(Message("Hello, World!").asJson)
+    Ok(Json.obj("message" -> Json.string("Hello, World!")))
+      .withHeader("Server" -> "finch")
+      .withHeader("Date" -> dateFormat.format(new Date()))
   }
 
-  val plaintext = get("plaintext") {
-    "Hello, World!"
+  val plaintext: Endpoint[String] = get("plaintext") {
+    Ok("Hello, World!")
+      .withHeader("Server" -> "finch")
+      .withHeader("Date" -> dateFormat.format(new Date()))
+      .withContentType(Some("text/plain"))
   }
 
-  val api: Service[Request, Response] = (json :+: plaintext).toService
-
-  Await.ready(
-    Httpx.serve(":9000", api)
+  Await.ready(Http.server
+    .withCompressionLevel(0)
+    .withStatsReceiver(NullStatsReceiver)
+    .withTracer(NullTracer)
+    .serve(":9000", (json :+: plaintext).toService)
   )
 }

+ 11 - 0
frameworks/Scala/fintrospect/.gitignore

@@ -0,0 +1,11 @@
+target/
+project/target
+bin/
+logs/
+.idea/
+.cache
+.classpath
+.project
+/bin/
+tools/
+sbt

+ 22 - 0
frameworks/Scala/fintrospect/README.md

@@ -0,0 +1,22 @@
+#fintrospect Benchmarking Test
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java Oracle 1.8.0_25](http://www.oracle.com/technetwork/java/javase)
+* [fintrospect 12.4.0](https://github.com/daviddenton/fintrospect)
+* [finagle 6.33.0](https://github.com/twitter/finagle)
+
+## Test URLs
+
+### JSON Encoding Test
+http://localhost:9000/json
+
+### Plaintext Test
+http://localhost:9000/plaintext
+
+## How to run
+sbt 'oneJar'
+
+`java -jar target/scala-2.11/*fintrospect*one-jar.jar`
+

+ 23 - 0
frameworks/Scala/fintrospect/benchmark_config.json

@@ -0,0 +1,23 @@
+{
+  "framework": "fintrospect",
+  "tests": [{
+    "default": {
+      "orm": "Raw",
+      "database_os": "Linux",
+      "setup_file": "setup",
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "port": 9000,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "None",
+      "framework": "fintrospect",
+      "language": "Scala",
+      "platform": "Netty",
+      "webserver": "None",
+      "os": "Linux",
+      "display_name": "fintrospect",
+      "notes": ""
+    }
+  }]
+}

+ 21 - 0
frameworks/Scala/fintrospect/build.sbt

@@ -0,0 +1,21 @@
+name := """techempower-benchmarks-fintrospect"""
+
+version := "0.0.1"
+
+scalaVersion := "2.11.7"
+
+resolvers += "JCenter" at "https://jcenter.bintray.com"
+
+com.github.retronym.SbtOneJar.oneJarSettings
+
+mainClass in(Compile, run) := Some("FintrospectBenchmarkServer")
+
+libraryDependencies ++= Seq(
+  "com.twitter" %% "finagle-http" % "6.33.0",
+  "io.github.daviddenton" %% "fintrospect" % "12.4.0",
+  "io.circe" %% "circe-core" % "0.3.0",
+  "io.circe" %% "circe-parser" % "0.3.0",
+  "io.circe" %% "circe-generic" % "0.3.0"
+)
+
+resolvers += Resolver.sonatypeRepo("snapshots")

+ 4 - 0
frameworks/Scala/fintrospect/project/build.properties

@@ -0,0 +1,4 @@
+#Activator-generated Properties
+#Wed Feb 25 16:26:13 CET 2015
+template.uuid=6a24da4f-6985-4cd1-a841-205d69ced830
+sbt.version=0.13.7

+ 1 - 0
frameworks/Scala/fintrospect/project/plugins.sbt

@@ -0,0 +1 @@
+addSbtPlugin("org.scala-sbt.plugins" % "sbt-onejar" % "0.8")

+ 7 - 0
frameworks/Scala/fintrospect/setup.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends java sbt
+
+sbt 'oneJar' -batch
+
+java -jar target/scala-2.11/*fintrospect*one-jar.jar &

+ 52 - 0
frameworks/Scala/fintrospect/src/main/scala/FintrospectBenchmarkServer.scala

@@ -0,0 +1,52 @@
+import java.time.ZonedDateTime._
+import java.time.format.DateTimeFormatter
+import java.time.format.DateTimeFormatter.RFC_1123_DATE_TIME
+import java.time.{ZonedDateTime, ZoneId}
+import javax.swing.text.DateFormatter
+
+import com.twitter.finagle.http.Method.Get
+import com.twitter.finagle.http.Request
+import com.twitter.finagle.http.Status._
+import com.twitter.finagle.http.path.Root
+import com.twitter.finagle.stats.NullStatsReceiver
+import com.twitter.finagle.tracing.NullTracer
+import com.twitter.finagle.{Http, Service}
+import com.twitter.util.Await
+import io.circe._
+import io.circe.generic.auto._
+import io.circe.parser._
+import io.circe.syntax._
+import io.fintrospect.formats.json.Circe.ResponseBuilder._
+import io.fintrospect.formats.json.Circe.JsonFormat._
+import io.fintrospect.formats.json.Circe.ResponseBuilder._
+import io.fintrospect.{ModuleSpec, RouteSpec}
+
+object FintrospectBenchmarkServer extends App {
+
+  def plainTextHelloWorld() = {
+    import io.fintrospect.formats.PlainText.ResponseBuilder._
+    Service.mk { r: Request => Ok("Hello, World!")
+      .withHeaders("Server" -> "Example", "Date" -> RFC_1123_DATE_TIME.format(now()))
+    }
+  }
+
+  def jsonHelloWorld() = {
+    case class Message(message: String)
+
+    Service.mk { r: Request => Ok(encode(Message("Hello, World!")))
+      .withHeaders("Server" -> "Example", "Date" -> RFC_1123_DATE_TIME.format(now()))
+    }
+  }
+
+  val module = ModuleSpec(Root)
+    .withRoute(RouteSpec().at(Get) / "plaintext" bindTo plainTextHelloWorld)
+    .withRoute(RouteSpec().at(Get) / "json" bindTo jsonHelloWorld)
+
+  Await.ready(
+    Http.server
+      .withCompressionLevel(0)
+      .withStatsReceiver(NullStatsReceiver)
+      .withTracer(NullTracer)
+      .serve(":9000", module.toService)
+  )
+}

+ 1 - 1
frameworks/Scala/http4s/build.sbt

@@ -25,7 +25,7 @@ libraryDependencies ++= Seq(
 	"org.scalaz" %% "scalaz-core" % scalazVersion,
 	"org.scalaz" %% "scalaz-concurrent" % scalazVersion,
 	"com.github.alexarchambault" %% "argonaut-shapeless_6.1" % "0.3.1",
-	"org.postgresql" % "postgresql" % "9.4-1204-jdbc4"
+	"org.postgresql" % "postgresql" % "9.4.1208"
 )
 
 mainClass in oneJar := Some("http4s.techempower.benchmark.WebServer")

+ 3 - 2
frameworks/Scala/play2-scala/play2-scala/app/controllers/Application.scala

@@ -14,10 +14,11 @@ class Application extends Controller {
 
   // Easy ones
   case class HelloWorld(message: String)
+  implicit val helloWorldWrites = Json.writes[HelloWorld]
 
   def getJsonMessage = Action {
     val helloWorld = HelloWorld(message = "Hello, World!")
-    Ok(Json.toJson(helloWorld)(Json.writes[HelloWorld])).withHeaders(CONTENT_TYPE -> "application/json")
+    Ok(Json.toJson(helloWorld)).withHeaders(CONTENT_TYPE -> "application/json")
   }
 
   val plaintext = Action {
@@ -25,4 +26,4 @@ class Application extends Controller {
     // BUT the test harness has a WARN state and says we don't need it.
     Ok("Hello, World!").withHeaders(CONTENT_TYPE -> "text/plain")
   }
-}
+}

+ 1 - 1
frameworks/Scala/scruffy/src/main/scala/scruffy/examples/Test2Endpoint.scala

@@ -21,7 +21,7 @@ object Test2Endpoint extends HttpModule {
   //  collection.save(DBObject("_id" -> k, "id" -> k, "randomNumber" -> random.nextInt(10000).toDouble))
 
   get("db") { req =>
-    val id = ThreadLocalRandom.current.nextInt(10000)
+    val id = 1 + ThreadLocalRandom.current.nextInt(10000)
     val dbo = collection.findOne(DBObject("_id" -> id), fields)
     val randomNumber = Math.round(dbo.get("randomNumber").toString.toFloat)
     Output(id, randomNumber).json

+ 1 - 1
frameworks/Ur/urweb/setup.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-VERSION=20150520
+VERSION=20160213
 COMPILER=${IROOT}/urweb
 
 RETCODE=$(fw_exists ${COMPILER}.installed)

+ 3 - 3
toolset/setup/linux/languages/rust.sh

@@ -5,10 +5,10 @@ RETCODE=$(fw_exists $IROOT/rust.installed)
   source $IROOT/rust.installed;
   return 0; }
 
-fw_get -O https://static.rust-lang.org/dist/rust-1.0.0-x86_64-unknown-linux-gnu.tar.gz
-fw_untar rust-1.0.0-x86_64-unknown-linux-gnu.tar.gz
+fw_get -O https://static.rust-lang.org/dist/rust-1.6.0-x86_64-unknown-linux-gnu.tar.gz
+fw_untar rust-1.6.0-x86_64-unknown-linux-gnu.tar.gz
 (
-	cd rust-1.0.0-x86_64-unknown-linux-gnu
+	cd rust-1.6.0-x86_64-unknown-linux-gnu
 	./install.sh --prefix=$IROOT/rust
 )