Răsfoiți Sursa

fixes merge conflict

Keith Newman 10 ani în urmă
părinte
comite
86238fd675
88 a modificat fișierele cu 1510 adăugiri și 553 ștergeri
  1. 13 10
      .travis.yml
  2. 1 1
      frameworks/Java/play2-java/install.sh
  3. 2 2
      frameworks/Java/play2-java/play2-java-ebean-bonecp/build.sbt
  4. 1 1
      frameworks/Java/play2-java/play2-java-ebean-bonecp/project/plugins.sbt
  5. 3 3
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/build.sbt
  6. 46 18
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf
  7. 1 1
      frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt
  8. 3 3
      frameworks/Java/play2-java/play2-java-jpa-bonecp/build.sbt
  9. 1 1
      frameworks/Java/play2-java/play2-java-jpa-bonecp/project/plugins.sbt
  10. 4 4
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt
  11. 47 19
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf
  12. 1 1
      frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt
  13. 1 1
      frameworks/Java/play2-java/play2-java/build.sbt
  14. 1 1
      frameworks/Java/play2-java/play2-java/project/plugins.sbt
  15. 1 1
      frameworks/Java/play2-java/setup_java.sh
  16. 1 1
      frameworks/Java/play2-java/setup_java_ebean_bonecp.sh
  17. 1 1
      frameworks/Java/play2-java/setup_java_ebean_hikaricp.sh
  18. 1 1
      frameworks/Java/play2-java/setup_java_jpa_bonecp.sh
  19. 1 1
      frameworks/Java/play2-java/setup_java_jpa_hikaricp.sh
  20. 45 8
      frameworks/Java/vertx/README.md
  21. 165 41
      frameworks/Java/vertx/WebServer.java
  22. 2 1
      frameworks/Java/vertx/app.js
  23. 2 0
      frameworks/Java/vertx/benchmark_config.json
  24. 9 1
      frameworks/Java/vertx/install.sh
  25. 1 1
      frameworks/Java/vertx/setup.sh
  26. 1 1
      frameworks/Java/vertx/source_code
  27. 2 2
      frameworks/JavaScript/express/README.md
  28. 104 64
      frameworks/JavaScript/express/app.js
  29. 1 0
      frameworks/JavaScript/express/benchmark_config.json
  30. 8 5
      frameworks/JavaScript/express/package.json
  31. 2 2
      frameworks/JavaScript/express/setup.sh
  32. 2 2
      frameworks/JavaScript/hapi/README.md
  33. 73 38
      frameworks/JavaScript/hapi/app.js
  34. 1 0
      frameworks/JavaScript/hapi/benchmark_config.json
  35. 6 5
      frameworks/JavaScript/hapi/package.json
  36. 2 2
      frameworks/JavaScript/hapi/setup.sh
  37. 0 0
      frameworks/JavaScript/hapi/views/fortunes.html
  38. 5 0
      frameworks/JavaScript/koa/app.js
  39. 2 2
      frameworks/JavaScript/koa/setup.sh
  40. 16 5
      frameworks/JavaScript/nodejs/README.md
  41. 6 4
      frameworks/JavaScript/nodejs/benchmark_config.json
  42. 285 213
      frameworks/JavaScript/nodejs/hello.js
  43. 5 5
      frameworks/JavaScript/nodejs/package.json
  44. 2 2
      frameworks/JavaScript/nodejs/setup.sh
  45. 13 12
      frameworks/Lua/lapis/config.lua
  46. 8 8
      frameworks/Lua/lapis/config.moon
  47. 1 2
      frameworks/Lua/lapis/nginx.conf
  48. 51 21
      frameworks/Lua/openresty/app.lua
  49. 2 1
      frameworks/Lua/openresty/benchmark_config.json
  50. 3 1
      frameworks/Lua/openresty/install.sh
  51. 11 2
      frameworks/Lua/openresty/nginx.conf
  52. 1 1
      frameworks/PHP/php-laravel/app/config/session.php
  53. 25 4
      frameworks/PHP/php-laravel/deploy/nginx.conf
  54. 2 1
      frameworks/PHP/php-laravel/install.sh
  55. 38 0
      frameworks/Python/klein/README.md
  56. 123 0
      frameworks/Python/klein/app.py
  57. 27 0
      frameworks/Python/klein/benchmark_config.json
  58. 19 0
      frameworks/Python/klein/install.sh
  59. 6 0
      frameworks/Python/klein/requirements.txt
  60. 6 0
      frameworks/Python/klein/setup.sh
  61. 20 0
      frameworks/Python/klein/templates/fortunes.html
  62. 6 1
      frameworks/Python/pyramid/create_database.py
  63. 1 1
      frameworks/Python/pyramid/frameworkbenchmarks/tests.py
  64. 5 3
      frameworks/Python/pyramid/frameworkbenchmarks/views.py
  65. 1 1
      frameworks/Python/turbogears/app.py
  66. 8 0
      frameworks/Scala/colossus/.gitignore
  67. 30 0
      frameworks/Scala/colossus/README.md
  68. 23 0
      frameworks/Scala/colossus/benchmark_config.json
  69. 14 0
      frameworks/Scala/colossus/build.sbt
  70. 3 0
      frameworks/Scala/colossus/install.sh
  71. 1 0
      frameworks/Scala/colossus/project/plugins.sbt
  72. 9 0
      frameworks/Scala/colossus/setup.sh
  73. 38 0
      frameworks/Scala/colossus/src/main/scala/example/Main.scala
  74. 3 0
      frameworks/Scala/http4s/.gitignore
  75. 26 0
      frameworks/Scala/http4s/README.md
  76. 23 0
      frameworks/Scala/http4s/benchmark_config.json
  77. 17 0
      frameworks/Scala/http4s/build.sbt
  78. 3 0
      frameworks/Scala/http4s/install.sh
  79. 1 0
      frameworks/Scala/http4s/project/plugins.sbt
  80. 9 0
      frameworks/Scala/http4s/setup.sh
  81. 29 0
      frameworks/Scala/http4s/src/main/scala/WebServer.scala
  82. 2 1
      frameworks/Scala/play2-scala/benchmark_config.json
  83. 10 0
      frameworks/Scala/play2-scala/play2-scala/app/controllers/Application.scala
  84. 1 0
      frameworks/Scala/play2-scala/play2-scala/conf/routes
  85. 1 1
      frameworks/Ur/urweb/install.sh
  86. 3 2
      toolset/benchmark/benchmarker.py
  87. 10 6
      toolset/benchmark/framework_test.py
  88. 0 9
      toolset/setup/linux/frameworks/vertx.sh

+ 13 - 10
.travis.yml

@@ -1,5 +1,5 @@
 language: python
-python: 
+python:
   - "2.7"
 
 env:
@@ -9,12 +9,12 @@ env:
     # we end up starting ~200+ different workers. Seems that ~100 is the limit
     # before their website starts to lag heavily
     #
-    # Here's the bash if you need to update this. Be sure to maintain the 
+    # Here's the bash if you need to update this. Be sure to maintain the
     # lines that are currently commented out (these cannot run in Travis)
-    #   cd frameworks 
+    #   cd frameworks
     #   find . -type d -depth 2 | sed 's|./|    - "TESTDIR=|' | sed 's/$/"/g'
     #
-    #  
+    #
     - "TESTDIR=C/lwan"
     - "TESTDIR=C/duda"
     - "TESTDIR=C/haywire"
@@ -127,6 +127,7 @@ env:
     - "TESTDIR=Python/falcon"
     - "TESTDIR=Python/flask"
     - "TESTDIR=Python/historical"
+    - "TESTDIR=Python/klein"
     - "TESTDIR=Python/pyramid"
     - "TESTDIR=Python/tornado"
     - "TESTDIR=Python/turbogears"
@@ -142,6 +143,7 @@ env:
     - "TESTDIR=Ruby/rails"
     - "TESTDIR=Ruby/rails-stripped"
     - "TESTDIR=Ruby/sinatra"
+    - "TESTDIR=Scala/colossus"
     - "TESTDIR=Scala/finagle"
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/plain"
@@ -151,10 +153,11 @@ env:
     - "TESTDIR=Scala/spray"
     - "TESTDIR=Scala/spray-es"
     - "TESTDIR=Scala/unfiltered"
+    - "TESTDIR=Scala/http4s"
     - "TESTDIR=Ur/urweb"
 
 before_install:
-  # Need to install python modules before using 
+  # Need to install python modules before using
   # python
   - pip install -r requirements.txt
 
@@ -163,15 +166,15 @@ before_install:
   - ./toolset/run-ci.py cisetup "$TESTDIR"
 
 addons:
-  postgresql: "9.3" 
+  postgresql: "9.3"
 
 install:
   # Install prerequisites
   - ./toolset/run-ci.py prereq "$TESTDIR"
-  
-  # Install software for this framework  
+
+  # Install software for this framework
   - ./toolset/run-ci.py install "$TESTDIR"
-   
-script: 
+
+script:
   # Pick one test in this directory and verify
   - time ./toolset/run-ci.py verify "$TESTDIR"

+ 1 - 1
frameworks/Java/play2-java/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends java7 sbt
+fw_depends java8 sbt

+ 2 - 2
frameworks/Java/play2-java/play2-java-ebean-bonecp/build.sbt

@@ -4,10 +4,10 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaEbean,
-  "mysql" % "mysql-connector-java" % "5.1.33"
+  "mysql" % "mysql-connector-java" % "5.1.35"
 )

+ 1 - 1
frameworks/Java/play2-java/play2-java-ebean-bonecp/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.8")

+ 3 - 3
frameworks/Java/play2-java/play2-java-ebean-hikaricp/build.sbt

@@ -4,13 +4,13 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaEbean,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "com.edulify" %% "play-hikaricp" % "1.5.0"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "com.edulify" %% "play-hikaricp" % "2.0.4"
 )
 
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)

+ 46 - 18
frameworks/Java/play2-java/play2-java-ebean-hikaricp/conf/application.conf

@@ -29,25 +29,53 @@ application.langs="en"
 #
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # db.default.jndiName=DefaultDS
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.user=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
 
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to 
-# 5 with 3 partitions means you will have 15 unique connections to the 
-# database.
-
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
-
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
+db {
+  default {
+
+    jndiName="DefaultDS"
+
+    dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+    dataSource {
+      user=benchmarkdbuser
+      password=benchmarkdbpass
+      databaseName=hello_world
+      serverName=127.0.0.1
+      port=3306
+
+      jdbcCompliantTruncation=false
+      elideSetAutoCommits=true
+      useLocalSessionState=true
+      cachePrepStmts=true
+      cacheCallableStmts=true
+      cacheServerConfiguration=true
+      cacheResultSetMetadata=true
+      alwaysSendSetIsolation=false
+      prepStmtCacheSize=4096
+      prepStmtCacheSqlLimit=2048
+      zeroDateTimeBehavior=convertToNull
+      traceProtocol=false
+      useUnbufferedInput=false
+      useReadAheadInput=false
+      maintainTimeStats=false
+      useServerPrepStmts=true
+    }
+
+    partitionCount=4
+
+    # The number of connections to create per partition. Setting this to
+    # 5 with 3 partitions means you will have 15 unique connections to the
+    # database.
+
+    # This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
+    maxConnectionsPerPartition=64
+
+    # The number of initial connections, per partition.
+    #
+    # This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
+    minConnectionsPerPartition=64
+  }
+}
 
 dbplugin=disabled
 

+ 1 - 1
frameworks/Java/play2-java/play2-java-ebean-hikaricp/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.8")

+ 3 - 3
frameworks/Java/play2-java/play2-java-jpa-bonecp/build.sbt

@@ -2,15 +2,15 @@ name := "play2-java-jpa-bonecp"
 
 version := "1.0-SNAPSHOT"
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "org.hibernate" % "hibernate-entitymanager" % "4.3.9.Final"
   )
 
 dependencyOverrides += "com.jolbox" % "bonecp" % "0.8.0.RELEASE"

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa-bonecp/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.8")

+ 4 - 4
frameworks/Java/play2-java/play2-java-jpa-hikaricp/build.sbt

@@ -4,14 +4,14 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"
 
 libraryDependencies ++= Seq(
   javaJdbc,
   javaJpa,
-  "mysql" % "mysql-connector-java" % "5.1.33",
-  "org.hibernate" % "hibernate-entitymanager" % "4.3.6.Final",
-  "com.edulify" %% "play-hikaricp" % "1.5.0"
+  "mysql" % "mysql-connector-java" % "5.1.35",
+  "org.hibernate" % "hibernate-entitymanager" % "4.3.9.Final",
+  "com.edulify" %% "play-hikaricp" % "2.0.4"
 )
 
 resolvers += Resolver.url("Edulify Repository", url("http://edulify.github.io/modules/releases/"))(Resolver.ivyStylePatterns)

+ 47 - 19
frameworks/Java/play2-java/play2-java-jpa-hikaricp/conf/application.conf

@@ -44,26 +44,54 @@ application.langs="en"
 # You can expose this datasource via JNDI if needed (Useful for JPA)
 # db.default.jndiName=DefaultDS
 
-db.default.driver= com.mysql.jdbc.Driver
-db.default.url="jdbc:mysql://127.0.0.1:3306/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-db.default.user=benchmarkdbuser
-db.default.password=benchmarkdbpass
-db.default.jndiName=DefaultDS
-jpa.default=defaultPersistenceUnit
-
-db.default.partitionCount=4
-
-# The number of connections to create per partition. Setting this to
-# 5 with 3 partitions means you will have 15 unique connections to the
-# database..
-#
-# This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
-db.default.maxConnectionsPerPartition=64
+db {
+  default {
+
+    jndiName="DefaultDS"
+
+    dataSourceClassName=com.mysql.jdbc.jdbc2.optional.MysqlDataSource
+    dataSource {
+      user=benchmarkdbuser
+      password=benchmarkdbpass
+      databaseName=hello_world
+      serverName=127.0.0.1
+      port=3306
+
+      jdbcCompliantTruncation=false
+      elideSetAutoCommits=true
+      useLocalSessionState=true
+      cachePrepStmts=true
+      cacheCallableStmts=true
+      cacheServerConfiguration=true
+      cacheResultSetMetadata=true
+      alwaysSendSetIsolation=false
+      prepStmtCacheSize=4096
+      prepStmtCacheSqlLimit=2048
+      zeroDateTimeBehavior=convertToNull
+      traceProtocol=false
+      useUnbufferedInput=false
+      useReadAheadInput=false
+      maintainTimeStats=false
+      useServerPrepStmts=true
+    }
+
+    partitionCount=4
+
+    # The number of connections to create per partition. Setting this to
+    # 5 with 3 partitions means you will have 15 unique connections to the
+    # database.
+
+    # This value maps to the maximumPoolSize for HickariCP (db.default.partitionCount * db.default.maxConnectionsPerPartition)
+    maxConnectionsPerPartition=64
+
+    # The number of initial connections, per partition.
+    #
+    # This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
+    minConnectionsPerPartition=64
+  }
+}
 
-# The number of initial connections, per partition.
-#
-# This maps to the minimumIdle connections for HikariCP (db.default.partitionCount * db.default.minConnectionsPerPartition)
-db.default.minConnectionsPerPartition=64
+jpa.default=defaultPersistenceUnit
 
 dbplugin=disabled
 

+ 1 - 1
frameworks/Java/play2-java/play2-java-jpa-hikaricp/project/plugins.sbt

@@ -1,4 +1,4 @@
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // The Play plugin
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.8")

+ 1 - 1
frameworks/Java/play2-java/play2-java/build.sbt

@@ -4,4 +4,4 @@ version := "1.0-SNAPSHOT"
 
 lazy val root = (project in file(".")).enablePlugins(PlayJava)
 
-scalaVersion := "2.11.4"
+scalaVersion := "2.11.6"

+ 1 - 1
frameworks/Java/play2-java/play2-java/project/plugins.sbt

@@ -5,4 +5,4 @@ logLevel := Level.Warn
 resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
 
 // Use the Play sbt plugin for Play projects
-addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.7")
+addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.8")

+ 1 - 1
frameworks/Java/play2-java/setup_java.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_ebean_bonecp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-ebean-bonecp
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_ebean_hikaricp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-ebean-hikaricp
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_jpa_bonecp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-jpa-bonecp
 

+ 1 - 1
frameworks/Java/play2-java/setup_java_jpa_hikaricp.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
 
 # load java environment variables
-source $IROOT/java7.installed
+source $IROOT/java8.installed
 
 cd play2-java-jpa-hikaricp
 

+ 45 - 8
frameworks/Java/vertx/README.md

@@ -1,26 +1,63 @@
-# Vertx Benchmarking Test
+# Vertx 2.x Benchmarking Test
 
-This is the vertx portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+This is the vertx 2.x portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### Plaintext Test
+
+* [Plaintext test source](WebServer.java)
+
+### JSON Serialization Test
 
-### JSON Encoding Test
 * [JSON test source](WebServer.java)
 
-### Data-Store/Database Mapping Test
+### Database Single query Test
+
+* [Database Single query test source](WebServer.java)
+
+### Database Multiple queries Test
+
+* [Database Multiple queries test source](WebServer.java)
+
+### Database Data updates Test
+
+* [Database Data updates test source](WebServer.java)
+
+### Fortunes Test
 
-* [Database test source](WebServer.java)
+* [Fortunes test source](WebServer.java)
 
 ## Versions
 
-* [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
-* [vertx 1.3.1](http://vertx.io/)
+* [Java OpenJDK 1.7.0_79](http://openjdk.java.net/)
+* [vertx 2.1.5](http://vertx.io/)
 
 
 ## Test URLs
 
+### Plaintext Test
+
+    http://localhost:8080/plaintext
+
 ### JSON Encoding Test
 
     http://localhost:8080/json
 
 ### Database Mapping Test
 
-    http://localhost:8080/db?queries=5
+    http://localhost:8080/db?queries=5
+
+### Database Single query Test
+
+    http://localhost:8080/db
+
+### Database Multiple queries Test
+
+    http://localhost:8080/queries?queries=5
+
+### Database Data updates Test
+
+    http://localhost:8080/updates?queries=3
+
+### Fortunes Test
+
+    http://localhost:8080/fortunes

+ 165 - 41
frameworks/Java/vertx/WebServer.java

@@ -15,15 +15,67 @@ import java.util.Date;
 import java.util.Random;
 import java.util.concurrent.ThreadLocalRandom;
 
+import freemarker.template.Template;
+import freemarker.template.Configuration;
+import java.io.StringReader;
+import java.io.Writer;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
 public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 
-  private Buffer helloWorldBuffer = new Buffer("Hello, World!");
-  private String helloWorldContentLength = String.valueOf(helloWorldBuffer.length());
-  private DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
+  private final Buffer helloWorldBuffer = new Buffer("Hello, World!");
+  private final String helloWorldContentLength = String.valueOf(helloWorldBuffer.length());
+  private final DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
+  private final Random random = ThreadLocalRandom.current();
   private String dateString;
 
+  private static final String PATH_PLAINTEXT = "/plaintext";
+  private static final String PATH_JSON = "/json";
+  private static final String PATH_DB = "/db";
+  private static final String PATH_QUERIES = "/queries";
+  private static final String PATH_UPDATES = "/updates";
+  private static final String PATH_FORTUNES = "/fortunes";
+  private static final String RESPONSE_TYPE_PLAIN = "text/plain";
+  private static final String RESPONSE_TYPE_HTML = "text/html";
+  private static final String RESPONSE_TYPE_JSON = "application/json";
+  private static final String HEADER_CONTENT_TYPE = "Content-Type";
+  private static final String HEADER_CONTENT_LENGTH = "Content-Length";
+  private static final String HEADER_SERVER = "Server";
+  private static final String HEADER_SERVER_VERTX = "vert.x";
+  private static final String HEADER_DATE = "Date";
+  private static final String MONGO_ADDRESS = "hello.persistor";
+  private static final String FREEMARKER_ADDRESS = "vertx.freemarker";
+  private static final String UNDERSCORE_ID = "_id";
+  private static final String TEXT_ID = "id";
+  private static final String RANDOM_NUMBER = "randomNumber";
+  private static final String TEXT_RESULT = "result";
+  private static final String TEXT_RESULTS = "results";
+  private static final String TEXT_QUERIES = "queries";
+  private static final String TEXT_MESSAGE = "message";
+  private static final String TEXT_MESSAGES = "messages";
+  private static final String ADD_FORTUNE_MESSAGE = "Additional fortune added at request time.";
+  private static final String HELLO_WORLD = "Hello, world!";
+  private static final String TEXT_ACTION = "action";
+  private static final String TEXT_CRITERIA = "criteria";
+  private static final String TEXT_UPDATE = "update";
+  private static final String TEXT_OBJ_NEW = "objNew";
+  private static final String TEXT_FINDONE = "findone";
+  private static final String TEXT_FIND = "find";
+  private static final String TEXT_COLLECTION = "collection";
+  private static final String TEXT_WORLD = "World";
+  private static final String TEXT_FORTUNE = "Fortune";
+  private static final String TEXT_MATCHER = "matcher";
+  private static final String TEMPLATE_FORTUNE = "<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><#list messages as message><tr><td>${message.id?html}</td><td>${message.message?html}</td></tr></#list></table></body></html>";
+  
+  private Template ftlTemplate;
+
   @Override
   public void start() {
+    try { ftlTemplate = new Template(TEXT_FORTUNE, new StringReader(TEMPLATE_FORTUNE), new Configuration(Configuration.VERSION_2_3_22)); } catch (Exception ex) { ex.printStackTrace(); }
     vertx.createHttpServer().requestHandler(WebServer.this).listen(8080);
     vertx.setPeriodic(1000, new Handler<Long>() {
       @Override
@@ -36,19 +88,24 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 
   @Override
   public void handle(HttpServerRequest req) {
-    String path = req.path();
-    switch (path) {
-      case "/plaintext":
+    switch (req.path()) {
+      case PATH_PLAINTEXT:
         handlePlainText(req);
         break;
-      case "/json":
+      case PATH_JSON:
         handleJson(req);
         break;
-      case "/db":
+      case PATH_DB:
         handleDbMongo(req);
         break;
-      case "/queries":
-        handleQueriesMongo(req);
+      case PATH_QUERIES:
+        handleDBMongo(req,false);
+        break;
+      case PATH_UPDATES:
+        handleDBMongo(req,true);
+        break;
+      case PATH_FORTUNES:
+        handleFortunes(req);
         break;
       default:
         req.response().setStatusCode(404);
@@ -60,21 +117,55 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     dateString = DATE_FORMAT.format(new Date());
   }
 
+  private void handleFortunes(HttpServerRequest req) {
+    final HttpServerResponse resp = req.response();
+    
+    vertx.eventBus().send(
+      MONGO_ADDRESS,
+      new JsonObject()
+          .putString(TEXT_ACTION, TEXT_FIND)
+          .putString(TEXT_COLLECTION, TEXT_FORTUNE),
+      new Handler<Message<JsonObject>>() {
+        @Override
+        public void handle(Message<JsonObject> reply) {
+          JsonArray results = reply.body().getArray(TEXT_RESULTS);
+          
+          List<Fortune> fortunes = new ArrayList<>();
+          for (Object fortune: results) {
+            fortunes.add(new Fortune(
+              ((JsonObject)fortune).getNumber(TEXT_ID).intValue(),
+              ((JsonObject)fortune).getString(TEXT_MESSAGE)));
+          }            
+          fortunes.add(new Fortune(0, ADD_FORTUNE_MESSAGE));
+          Collections.sort(fortunes);
+
+          Map model = new HashMap();
+          model.put(TEXT_MESSAGES, fortunes);
+          Writer writer = new StringWriter();
+          try { ftlTemplate.process(model, writer); } catch (Exception ex) { ex.printStackTrace(); }
+
+          Buffer buff = new Buffer(writer.toString());
+          setHeaders(resp, RESPONSE_TYPE_HTML, String.valueOf(buff.length()));
+          resp.end(buff);
+        }  
+    });
+  }
+
   private void handlePlainText(HttpServerRequest req) {
     HttpServerResponse resp = req.response();
-    setHeaders(resp, "text/plain", helloWorldContentLength);
+    setHeaders(resp, RESPONSE_TYPE_PLAIN, helloWorldContentLength);
     resp.end(helloWorldBuffer);
   }
 
   private void handleJson(HttpServerRequest req) {
-    Buffer buff = new Buffer(Json.encode(Collections.singletonMap("message", "Hello, world!")));
+    Buffer buff = new Buffer(Json.encode(Collections.singletonMap(TEXT_MESSAGE, HELLO_WORLD)));
     HttpServerResponse resp = req.response();
-    setHeaders(resp, "application/json", String.valueOf(buff.length()));
+    setHeaders(resp, RESPONSE_TYPE_JSON, String.valueOf(buff.length()));
     resp.end(buff);
   }
 
   private void handleDbMongo(final HttpServerRequest req) {
-    findRandom(ThreadLocalRandom.current(), new Handler<Message<JsonObject>>() {
+    findRandom(new Handler<Message<JsonObject>>() {
       @Override
       public void handle(Message<JsonObject> reply) {
         JsonObject world = getResultFromReply(reply);
@@ -86,72 +177,86 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 
   private JsonObject getResultFromReply(Message<JsonObject> reply) {
     JsonObject body = reply.body();
-    JsonObject world = body.getObject("result");
-    Object id = world.removeField("_id");
-    world.putValue("id", id);
+    JsonObject world = body.getObject(TEXT_RESULT);
+    Object id = world.removeField(UNDERSCORE_ID);
+    world.putValue(TEXT_ID, Integer.valueOf(((Double)id).intValue()));
     return world;
   }
 
-  private void handleQueriesMongo(final HttpServerRequest req) {
+  private void handleDBMongo(final HttpServerRequest req, boolean randomUpdates) {
     int queriesParam = 1;
     try {
-      queriesParam = Integer.parseInt(req.params().get("queries"));
+      queriesParam = Integer.parseInt(req.params().get(TEXT_QUERIES));
     } catch (NumberFormatException e) {
-      e.printStackTrace();
-    }
-    if (queriesParam < 1)
-    {
       queriesParam = 1;
     }
-    if (queriesParam > 500)
-    {
+    if (queriesParam < 1) {
+      queriesParam = 1;
+    } else if (queriesParam > 500) {
       queriesParam = 500;
     }
-    final MongoHandler dbh = new MongoHandler(req, queriesParam);
-    final Random random = ThreadLocalRandom.current();
+    final MongoHandler dbh = new MongoHandler(req, queriesParam, randomUpdates);
     for (int i = 0; i < queriesParam; i++) {
-      findRandom(random, dbh);
+      findRandom(dbh);
     }
   }
 
-  private void findRandom(Random random, Handler<Message<JsonObject>> handler) {
+  private void findRandom(Handler<Message<JsonObject>> handler) {
     vertx.eventBus().send(
-        "hello.persistor",
+        MONGO_ADDRESS,
         new JsonObject()
-            .putString("action", "findone")
-            .putString("collection", "World")
-            .putObject("matcher", new JsonObject().putNumber("_id", (random.nextInt(10000) + 1))),
+            .putString(TEXT_ACTION, TEXT_FINDONE)
+            .putString(TEXT_COLLECTION, TEXT_WORLD)
+            .putObject(TEXT_MATCHER, new JsonObject().putNumber(UNDERSCORE_ID, (random.nextInt(10000) + 1))),
         handler);
   }
 
+  private void updateRandom(JsonObject json) {
+    vertx.eventBus().send(
+        MONGO_ADDRESS,
+        new JsonObject()
+            .putString(TEXT_ACTION, TEXT_UPDATE)
+            .putString(TEXT_COLLECTION, TEXT_WORLD)
+            .putObject(TEXT_CRITERIA, new JsonObject().putValue(UNDERSCORE_ID, json.getValue(TEXT_ID)))
+            .putObject(TEXT_OBJ_NEW, json)
+             );
+  }
+
   private void sendResponse(HttpServerRequest req, String result) {
     Buffer buff = new Buffer(result);
     HttpServerResponse resp = req.response();
-    setHeaders(resp, "application/json", String.valueOf(buff.length()));
+    setHeaders(resp, RESPONSE_TYPE_JSON, String.valueOf(buff.length()));
     resp.end(buff);
   }
 
   private void setHeaders(HttpServerResponse resp, String contentType, String contentLength) {
-    resp.putHeader("Content-Type", contentType);
-    resp.putHeader("Content-Length", contentLength);
-    resp.putHeader("Server", "vert.x");
-    resp.putHeader("Date", dateString);
+    resp.putHeader(HEADER_CONTENT_TYPE, contentType);
+    resp.putHeader(HEADER_CONTENT_LENGTH, contentLength);
+    resp.putHeader(HEADER_SERVER, HEADER_SERVER_VERTX );
+    resp.putHeader(HEADER_DATE, dateString);
   }
 
-  private class MongoHandler implements Handler<Message<JsonObject>> {
+  private final class MongoHandler implements Handler<Message<JsonObject>> {
     private final HttpServerRequest req;
     private final int queries;
     private final JsonArray worlds;
+    private final Random random;
+    private final boolean randomUpdates;
 
-    public MongoHandler(HttpServerRequest request, int queriesParam) {
+    public MongoHandler(HttpServerRequest request, int queriesParam, boolean performRandomUpdates) {
       req = request;
       queries = queriesParam;
+      randomUpdates = performRandomUpdates;
+      random = ThreadLocalRandom.current();
       worlds = new JsonArray();
     }
-
     @Override
     public void handle(Message<JsonObject> reply) {
       JsonObject world = getResultFromReply(reply);
+      if (randomUpdates) {
+        world.putValue(RANDOM_NUMBER, (random.nextInt(10000) + 1));
+        updateRandom(world);        
+      }
       worlds.add(world);
       if (worlds.size() == this.queries) {
         // All queries have completed; send the response.
@@ -160,6 +265,25 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
       }
     }
   }
+  
+  public final class Fortune implements Comparable<Fortune> {
+    public int id;
+    public String message;
 
+    public int getId() {
+      return id;
+    }
+    public String getMessage() {
+      return message;
+    }
+    public Fortune(int id, String message) {
+      this.id = id;
+      this.message = message;
+    }
+    @Override
+    public int compareTo(Fortune other) {
+      return message.compareTo(other.message);
+    }
+  }  
 }
 

+ 2 - 1
frameworks/Java/vertx/app.js

@@ -3,7 +3,8 @@ var container = require('vertx/container')
 var persistorConf = {
   address: 'hello.persistor',
   db_name: 'hello_world',
-  host: 'localhost'
+  host: '127.0.0.1',
+  pool_size: 100
 }
 
 container.deployModule('io.vertx~mod-mongo-persistor~2.1.1', persistorConf, function (err, dep_id) {

+ 2 - 0
frameworks/Java/vertx/benchmark_config.json

@@ -7,6 +7,8 @@
       "db_url": "/db",
       "plaintext_url": "/plaintext",
       "query_url": "/queries?queries=",
+      "update_url": "/updates?queries=",
+      "fortune_url": "/fortunes",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 9 - 1
frameworks/Java/vertx/install.sh

@@ -1,3 +1,11 @@
 #!/bin/bash
 
-fw_depends java7 vertx 
+fw_depends java7
+
+RETCODE=$(fw_exists ${IROOT}/vert.x-2.1.5.installed)
+[ ! "$RETCODE" == 0 ] || { return 0; }
+
+fw_get http://dl.bintray.com/vertx/downloads/vert.x-2.1.5.tar.gz?direct=true -O vert.x-2.1.5.tar.gz
+fw_untar vert.x-2.1.5.tar.gz
+wget http://central.maven.org/maven2/org/freemarker/freemarker/2.3.22/freemarker-2.3.22.jar -O ${IROOT}/vert.x-2.1.5/lib/freemarker-2.3.22.jar
+touch ${IROOT}/vert.x-2.1.5.installed

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

@@ -4,4 +4,4 @@ source $IROOT/java7.installed
 
 sed -i 's|host: \x27.*\x27|host: \x27'"${DBHOST}"'\x27|g' app.js
 
-${IROOT}/vert.x-2.1.1/bin/vertx run app.js &
+${IROOT}/vert.x-2.1.5/bin/vertx run app.js &

+ 1 - 1
frameworks/Java/vertx/source_code

@@ -1,2 +1,2 @@
-./vertx/App.groovy
+./vertx/app.js
 ./vertx/WebServer.java

+ 2 - 2
frameworks/JavaScript/express/README.md

@@ -12,8 +12,8 @@ This is the Express portion of a [benchmarking test suite](../) comparing a vari
 
 ## Infrastructure Software Versions
 The tests were run with:
-* [Node.js v0.10.0](http://nodejs.org/)
-* [Express 3.1](http://expressjs.com/)
+* [Node.js v0.12.2](http://nodejs.org/)
+* [Express 4.12.3](http://expressjs.com/)
 
 ## Resources
 * http://nodejs.org/api/cluster.html

+ 104 - 64
frameworks/JavaScript/express/app.js

@@ -5,28 +5,56 @@
 
 var cluster = require('cluster')
   , numCPUs = require('os').cpus().length
-  , windows = require('os').platform() == 'win32'
   , express = require('express')
+  , Sequelize = require('sequelize')
   , mongoose = require('mongoose')
-  , async = require('async')
   , conn = mongoose.connect('mongodb://localhost/hello_world')
-  , connMap = { user: 'benchmarkdbuser', password: 'benchmarkdbpass', database: 'hello_world', host: 'localhost', charset: 'utf8' };
+  , async = require('async');
+
+// Middleware
+var bodyParser = require('body-parser')
+  , methodOverride = require('method-override')
+  , errorHandler = require('errorhandler');
 
 var Schema = mongoose.Schema
   , ObjectId = Schema.ObjectId;
 
-var WorldSchema = new Schema({
-    id                           : Number
-  , randomNumber                 : Number
-}, { collection : 'world' });
-var MWorld = conn.model('World', WorldSchema);
-
-if (!windows) {
-  var Mapper = require('mapper');
-  Mapper.connect(connMap, {verbose: false, strict: false});
-  var World = Mapper.map("World", "id", "randomNumber");
-  var Fortune = Mapper.map("Fortune", "id", "message");
-}
+var WorldSchema = new mongoose.Schema({
+    id          : Number,
+    randomNumber: Number
+  }, {
+    collection: 'world'
+  }),
+  MWorld = conn.model('World', WorldSchema);
+
+var sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', {
+  host: 'localhost',
+  dialect: 'mysql',
+  logging: false
+});
+
+var World = sequelize.define('World', {
+  id: {
+    type: 'Sequelize.INTEGER'
+  },
+  randomNumber: {
+    type: 'Sequelize.INTEGER'
+  }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
+var Fortune = sequelize.define('Fortune', {
+  id: {
+    type: 'Sequelize.INTEGER'
+  },
+  message: {
+    type: 'Sequelize.STRING'
+  }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
 
 if (cluster.isMaster) {
   // Fork workers.
@@ -41,95 +69,104 @@ if (cluster.isMaster) {
   var app = module.exports = express();
 
   // Configuration
-  app.configure(function(){
-    app.use(express.bodyParser());
-    app.use(express.methodOverride());
-    app.use(app.router);
+  // https://github.com/expressjs/method-override#custom-logic
+  app.use(bodyParser.urlencoded({extended: true}));
+  app.use(methodOverride(function(req, res){
+    if (req.body && typeof req.body === 'object' && '_method' in req.body) {
+      // look in urlencoded POST bodies and delete it
+      var method = req.body._method
+      delete req.body._method
+      return method
+    }
+  }));
 
-    app.set('view engine', 'jade');
-    app.set('views', __dirname + '/views');
+  // Set headers for all routes
+  app.use(function(req, res, next) {
+    res.setHeader("Server", "Express");
+    return next();
   });
 
-  app.configure('development', function() {
-    app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
-  });
+  app.set('view engine', 'jade');
+  app.set('views', __dirname + '/views');
 
-  app.configure('production', function() {
-    app.use(express.errorHandler());
-  });
+  // Check Node env.
+  var env = process.env.NODE_ENV || 'development';
+  if ('development' == env) {
+    app.use(errorHandler({ dumpExceptions: true, showStack: true }));
+  }
+  if ('production' == env) {
+    app.use(errorHandler());
+  }
 
   // Routes
 
   app.get('/json', function(req, res) {
-    res.send({ message: 'Hello, World!' })
+    res.send({ message: 'Hello, World!' });
+  });
+
+  app.get('/plaintext', function(req, res) {
+    res.header('Content-Type', 'text/plain').send('Hello, World!');
   });
   
   app.get('/mongoose', function(req, res) {
-    var queries = req.query.queries || 1,
-        worlds  = [],
-        queryFunctions = [];
+    var queries = isNaN(req.query.queries) ? 1 : parseInt(req.query.queries, 10)
+      , queryFunctions = [];
+
+    queries = Math.min(Math.max(queries, 1), 500);
 
     for (var i = 1; i <= queries; i++ ) {
       queryFunctions.push(function(callback) {
-        MWorld.findOne({ id: (Math.floor(Math.random() * 10000) + 1 )}).exec(function (err, world) {
-          worlds.push(world);
-          callback(null, 'success');
-        });
+        MWorld.findOne({ id: (Math.floor(Math.random() * 10000) + 1) }).exec(callback);
       });
     }
 
     async.parallel(queryFunctions, function(err, results) {
-      if (queries == 1) {
-        worlds = worlds[0];
+      if (!req.query.queries) {
+        results = results[0];
       }
-      res.send(worlds);
+      res.send(results);
     });
   });
 
-  app.get('/mysql-orm', function(req, res) {
-    if (windows) return res.send(501, 'Not supported on windows');
-    
+  app.get('/mysql-orm', function(req, res) {    
     var queries = isNaN(req.query.queries) ? 1 : parseInt(req.query.queries, 10)
-      , worlds  = []
       , queryFunctions = [];
 
     queries = Math.min(Math.max(queries, 1), 500);
 
     for (var i = 1; i <= queries; i++ ) {
       queryFunctions.push(function(callback) {
-        World.findById(Math.floor(Math.random()*10000) + 1, function (err, world) {
-          worlds.push(world);
-          callback(null, 'success');
-        });
+        World.findOne({
+          where: {
+            id: Math.floor(Math.random() * 10000) + 1}
+          }
+        ).complete(callback);
       });
     }
 
     async.parallel(queryFunctions, function(err, results) {
       if (!req.query.queries) {
-        worlds = worlds[0];
+        results = results[0];
       }
-      res.send(worlds);
+      res.setHeader("Content-Type", "application/json");
+      res.send(results);
     });
   });
 
   app.get('/fortune', function(req, res) {
-    if (windows) return res.send(501, 'Not supported on windows');
-    
-    Fortune.all(function (err, fortunes) {
+    Fortune.findAll().complete(function (err, fortunes) {
       var newFortune = {id: 0, message: "Additional fortune added at request time."};
       fortunes.push(newFortune);
-      fortunes.sort(sortFortunes);
+      fortunes.sort(function (a, b) {
+        return (a.message < b.message) ? -1 : 1;
+      });
 
       res.render('fortunes', {fortunes: fortunes});
     });
   });
 
-  function sortFortunes(a, b) {
-    return (a.message < b.message) ? -1 : (a.message > b.message) ? 1 : 0;
-  }
-
   app.get('/mongoose-update', function(req, res) {
-    var queries = req.query.queries || 1
+    var queries = isNaN(req.query.queries) ? 1 : parseInt(req.query.queries, 10)
       , selectFunctions = [];
 
     queries = Math.min(queries, 500);
@@ -163,16 +200,18 @@ if (cluster.isMaster) {
   });
 
   app.get('/mysql-orm-update', function(req, res) {
-    if (windows) return res.send(501, 'Not supported on windows');
-
-    var queries = req.query.queries || 1
+    var queries = isNaN(req.query.queries) ? 1 : parseInt(req.query.queries, 10)
       , selectFunctions = [];
 
-    queries = Math.min(queries, 500);
+    queries = Math.max(Math.min(queries, 500), 1);
 
     for (var i = 1; i <= queries; i++ ) {
       selectFunctions.push(function(callback) {
-        World.findById(Math.floor(Math.random() * 10000) + 1, callback);
+        World.findOne({
+          where: {
+            id: Math.floor(Math.random() * 10000) + 1}
+          }
+        ).complete(callback);
       });
     }
 
@@ -183,7 +222,7 @@ if (cluster.isMaster) {
         (function(i){
           updateFunctions.push(function(callback){
             worlds[i].randomNumber = Math.ceil(Math.random() * 10000);
-            World.save(worlds[i], callback);
+            worlds[i].save().complete(callback);
           });
         })(i);
       }
@@ -191,7 +230,8 @@ if (cluster.isMaster) {
       async.parallel(updateFunctions, function(err, updates) {
         res.send(worlds);
       });
-    });   
+    });  
+
   });
 
   app.listen(8080);

+ 1 - 0
frameworks/JavaScript/express/benchmark_config.json

@@ -4,6 +4,7 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",

+ 8 - 5
frameworks/JavaScript/express/package.json

@@ -3,11 +3,14 @@
   , "version": "0.0.1"
   , "private": true
   , "dependencies": {
-      "express": "3.1.0"
-    , "mongoose": "3.5.5" 
-    , "async": "0.2.5"
-    , "mysql-libmysqlclient": "1.5.2"
-    , "mapper": "0.2.4-pre"
+      "express": "4.12.3"
+    , "body-parser": "1.12.3"
+    , "method-override": "2.3.2"
+    , "errorhandler": "1.3.5"
+    , "mongoose": "4.0.1" 
+    , "async": "0.9.0"
     , "jade": "0.29.0"
+    , "sequelize": "2.0.6"
+    , "mysql": "2.6.2"
   }
 }

+ 2 - 2
frameworks/JavaScript/express/setup.sh

@@ -7,8 +7,8 @@ export NVM_HOME=${IROOT}/nvm
 # Used to avoid nvm's return 2 error.
 # Sourcing this functions if 0 is returned.
 source $NVM_HOME/nvm.sh || 0
-nvm install 0.10.8
-nvm use 0.10.8
+nvm install 0.12.2
+nvm use 0.12.2
 
 # update npm before app init
 npm install -g npm

+ 2 - 2
frameworks/JavaScript/hapi/README.md

@@ -12,8 +12,8 @@ This is the Hapi portion of a [benchmarking test suite](../) comparing a variety
 
 ## Infrastructure Software Versions
 The tests were run with:
-* [Node.js v0.10.0](http://nodejs.org/)
-* [Hapi 1.2.0](http://spumko.github.io/)
+* [Node.js v0.12.2](http://nodejs.org/)
+* [Hapi 8.4.0](http://hapijs.com/)
 
 ## Resources
 * http://nodejs.org/api/cluster.html

+ 73 - 38
frameworks/JavaScript/hapi/app.js

@@ -4,12 +4,11 @@
 
 var cluster = require('cluster'),
 	numCPUs = require('os').cpus().length,
-	windows = require('os').platform() == 'win32',
 	Hapi = require('hapi'),
+	Sequelize = require('sequelize'),
 	mongoose = require('mongoose'),
-	async = require('async'),
 	conn = mongoose.connect('mongodb://localhost/hello_world'),
-	connMap = { user: 'benchmarkdbuser', password: 'benchmarkdbpass', database: 'hello_world', host: 'localhost', charset: 'utf8' };
+	async = require('async');
 
 var WorldSchema = new mongoose.Schema({
 		id          : Number,
@@ -19,12 +18,34 @@ var WorldSchema = new mongoose.Schema({
 	}),
 	MWorld = conn.model('World', WorldSchema);
 
-if (!windows) {
-	var Mapper = require('mapper');
-	Mapper.connect(connMap, {verbose: false, strict: false});
-	var World = Mapper.map('World', 'id', 'randomNumber');
-	var Fortune = Mapper.map('Fortune', 'id', 'message');
-}
+var sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', {
+	host: 'localhost',
+	dialect: 'mysql',
+	logging: false
+});
+
+var World = sequelize.define('World', {
+	id: {
+		type: 'Sequelize.INTEGER'
+	},
+	randomNumber: {
+		type: 'Sequelize.INTEGER'
+	}
+}, {
+	timestamps: false,
+	freezeTableName: true
+});
+var Fortune = sequelize.define('Fortune', {
+	id: {
+		type: 'Sequelize.INTEGER'
+	},
+	message: {
+		type: 'Sequelize.STRING'
+	}
+}, {
+	timestamps: false,
+	freezeTableName: true
+});
 
 if (cluster.isMaster) {
 	// Fork workers.
@@ -36,28 +57,38 @@ if (cluster.isMaster) {
 		console.log('worker ' + worker.pid + ' died');
 	});
 } else {
-	var server = module.exports = Hapi.createServer(null, 8080, {
-		views: {
-			engines: {
-				handlebars: 'handlebars'
-			},
-			path: __dirname + '/views'
-		}
+	var server = module.exports = new Hapi.Server();
+	server.connection({port: 8080});
+	server.views({
+		engines: {
+			html: require('handlebars')
+		},
+		path: __dirname + '/views'
 	});
 
 	server.route({
 		method: 'GET',
 		path: '/json',
-		handler: function(req) {
-			req.reply({ message: 'Hello, World!' })
+		handler: function(req, reply) {
+			reply({ message: 'Hello, World!' }).header('Server', 'hapi');
+		}
+	});
+
+	server.route({
+		method: 'GET',
+		path: '/plaintext',
+		handler: function(req, reply) {
+			reply('Hello, World!')
+			 .header('Server', 'hapi')
+			 .header('Content-Type', 'text/plain');
 		}
 	});
 
 	server.route({
 		method: 'GET',
 		path: '/mongoose/{queries?}',
-		handler: function(req){
-			var queries = req.params.queries || 1,
+		handler: function(req, reply){
+			var queries = isNaN(req.params.queries) ? 1 : parseInt(req.params.queries, 10),
 				queryFunctions = [];
 
 			queries = Math.min(Math.max(queries, 1), 500);
@@ -69,10 +100,10 @@ if (cluster.isMaster) {
 			}
 
 			async.parallel(queryFunctions, function(err, results){
-				if (queries == 1) {
+				if (!req.params.queries) {
 					results = results[0];
 				}
-				req.reply(results).header('Server', 'hapi');
+				reply(results).header('Server', 'hapi');
 			});
 		}
 	});
@@ -81,8 +112,6 @@ if (cluster.isMaster) {
 		method: 'GET',
 		path: '/mysql-orm/{queries?}',
 		handler: function(req, reply){
-			if (windows) return req.reply(Hapi.error.internal('Not supported on windows'));
-
 			var queries = isNaN(req.params.queries) ? 1 : parseInt(req.params.queries, 10),
 				queryFunctions = [];
 
@@ -90,7 +119,11 @@ if (cluster.isMaster) {
 
 			for (var i = 1; i <= queries; i++) {
 				queryFunctions.push(function(callback){
-					World.findById(Math.floor(Math.random() * 10000) + 1, callback);
+					World.findOne({
+						where: {
+							id: Math.floor(Math.random() * 10000) + 1}
+						}
+					).complete(callback);
 				});
 			}
 
@@ -106,10 +139,8 @@ if (cluster.isMaster) {
 	server.route({
 		method: 'GET',
 		path: '/fortune',
-		handler: function(req){
-			if (windows) return req.reply(Hapi.error.internal('Not supported on windows'));
-
-			Fortune.all(function(err, fortunes){
+		handler: function(req,reply){
+			Fortune.findAll().complete(function(err, fortunes){
 				fortunes.push({
 					id: 0,
 					message: 'Additional fortune added at request time.'
@@ -118,7 +149,7 @@ if (cluster.isMaster) {
 					return (a.message < b.message) ? -1 : 1;
 				});
 
-				req.reply.view('fortunes.handlebars', {
+				reply.view('fortunes', {
 					fortunes: fortunes
 				}).header('Server', 'hapi');
 			});
@@ -128,8 +159,8 @@ if (cluster.isMaster) {
 	server.route({
 		method: 'GET',
 		path: '/mongoose-update/{queries?}',
-		handler: function(req){
-			var queries = req.params.queries || 1,
+		handler: function(req, reply){
+			var queries = isNaN(req.params.queries) ? 1 : parseInt(req.params.queries, 10),
 				selectFunctions = [];
 
 			queries = Math.max(Math.min(queries, 500), 1);
@@ -157,7 +188,7 @@ if (cluster.isMaster) {
 				}
 
 				async.parallel(updateFunctions, function(err, updates) {
-					req.reply(worlds).header('Server', 'hapi');
+					reply(worlds).header('Server', 'hapi');
 				});
 			});
 		}		
@@ -166,15 +197,19 @@ if (cluster.isMaster) {
 	server.route({
 		method: 'GET',
 		path: '/mysql-orm-update/{queries?}',
-		handler: function(req){
-			var queries = req.params.queries || 1,
+		handler: function(req,reply){
+			var queries = isNaN(req.params.queries) ? 1 : parseInt(req.params.queries, 10),
 				selectFunctions = [];
 
 			queries = Math.max(Math.min(queries, 500), 1);
 
 			for (var i = 1; i <= queries; i++) {
 				selectFunctions.push(function(callback){
-					World.findById(Math.floor(Math.random() * 10000) + 1, callback);
+					World.findOne({
+						where: {
+							id: Math.floor(Math.random() * 10000) + 1}
+						}
+					).complete(callback);
 				});
 			}
 
@@ -185,13 +220,13 @@ if (cluster.isMaster) {
 					(function(i){
 						updateFunctions.push(function(callback){
 							worlds[i].randomNumber = Math.ceil(Math.random() * 10000);
-							World.save(worlds[i], callback);
+							worlds[i].save().complete(callback);
 						});
 					})(i);
 				}
 
 				async.parallel(updateFunctions, function(err, updates) {
-					req.reply(worlds).header('Server', 'hapi');
+					reply(worlds).header('Server', 'hapi');
 				});
 			});
 		}

+ 1 - 0
frameworks/JavaScript/hapi/benchmark_config.json

@@ -4,6 +4,7 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
+      "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",

+ 6 - 5
frameworks/JavaScript/hapi/package.json

@@ -3,10 +3,11 @@
 	"version": "0.0.1",
 	"private": true,
 	"dependencies": {
-		"hapi": "1.2.0",
-		"mongoose": "3.5.5",
-		"async": "0.2.5",
-		"mapper": "0.2.4-pre",
-		"handlebars": "1.0.11"
+		"hapi": "8.4.0",
+		"mongoose": "4.0.1",
+		"async": "0.9.0",
+		"handlebars": "3.0.1",
+		"sequelize": "2.0.6",
+		"mysql": "2.6.2"
 	}
 }

+ 2 - 2
frameworks/JavaScript/hapi/setup.sh

@@ -6,8 +6,8 @@ export NVM_HOME=${IROOT}/nvm
 # Used to avoid nvm's return 2 error.
 # Sourcing this functions if 0 is returned.
 source $NVM_HOME/nvm.sh || 0
-nvm install 0.10.8
-nvm use 0.10.8
+nvm install 0.12.2
+nvm use 0.12.2
 
 # update npm before app init
 npm install -g npm

+ 0 - 0
frameworks/JavaScript/hapi/views/fortunes.handlebars → frameworks/JavaScript/hapi/views/fortunes.html


+ 5 - 0
frameworks/JavaScript/koa/app.js

@@ -80,16 +80,19 @@ if (cluster.isMaster) {
 
   // Route handlers
   function *jsonHandler() {
+    this.set('Server', 'Koa');
     this.body = {
       message: "Hello, world!"
     }
   }
 
   function *dbHandler() {
+    this.set('Server', 'Koa');
     this.body = yield worldQuery;
   }
 
   function *queriesHandler() {
+    this.set('Server', 'Koa');
     var numOfQueries = validateParam(this.query.queries);
     var queries = [];
     for (var i = 0; i < numOfQueries; i++) {
@@ -112,6 +115,7 @@ if (cluster.isMaster) {
   }
 
   function *updateHandler() {
+    this.set('Server', 'Koa');
     var numOfUpdates = validateParam(this.query.queries);
     var queries = [];
     for (var i = 0; i < numOfUpdates; i++) {
@@ -121,6 +125,7 @@ if (cluster.isMaster) {
   }
 
   function *textHandler() {
+    this.set('Server', 'Koa');
     this.body = 'Hello, world!';
   }
 

+ 2 - 2
frameworks/JavaScript/koa/setup.sh

@@ -6,8 +6,8 @@ export NVM_HOME=${IROOT}/nvm
 # Used to avoid nvm's return 2 error.
 # Sourcing this functions if 0 is returned.
 source $NVM_HOME/nvm.sh || 0
-nvm install 0.11.16
-nvm use 0.11.16
+nvm install 0.12.2
+nvm use 0.12.2
 
 # update npm before app init
 npm install -g npm

+ 16 - 5
frameworks/JavaScript/nodejs/README.md

@@ -12,23 +12,31 @@ This is the NodeJS portion of a [benchmarking test suite](../) comparing a varie
 
 ## Infrastructure Software Versions
 The tests were run with:
-* [Node.js v0.10.0](http://nodejs.org/)
-* [Mongoose 3.5.5](http://mongoosejs.com/)
-* [Mapper 0.2.4-pre](https://github.com/mgutz/mapper)
-* [MySQL 5.5.29](https://dev.mysql.com/)
+* [Node.js v0.12.2](http://nodejs.org/)
+* [Mongoose 4.0.1](http://mongoosejs.com/)
+* [Sequelize 2.0.6](https://github.com/sequelize/sequelize)
+* [Node MySQL 2.6.2](https://github.com/felixge/node-mysql/)
+* [Node MongoDB Driver 2.0.27](https://github.com/mongodb/node-mongodb-native)
 
 ## Test URLs
 ### JSON Encoding Test
 
 http://localhost:8080/json
 
+### Plaintext Test
+
+http://localhost:8080/plaintext
+
 ### Data-Store/Database Mapping Test
 
 MongoDB:
 http://localhost:8080/mongoose
 
+MongoDB Raw:
+http://localhost:8080/mongodb
+
 MySQL:
-http://localhost:8080/sequelize
+http://localhost:8080/mysql-orm
 
 MySQL Raw:
 http://localhost:8080/mysql
@@ -38,6 +46,9 @@ http://localhost:8080/mysql
 MongoDB:
 http://localhost:8080/mongoose?queries=2
 
+MongoDB Raw:
+http://localhost:8080/mongodb?queries=2
+
 MySQL:
 http://localhost:8080/mysql-orm?queries=2
 

+ 6 - 4
frameworks/JavaScript/nodejs/benchmark_config.json

@@ -24,6 +24,7 @@
       "setup_file": "setup",
       "db_url": "/mongoose",
       "query_url": "/mongoose?queries=",
+      "update_url": "/mongoose-update?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
@@ -41,9 +42,9 @@
     },
     "mongodb-raw": {
       "setup_file": "setup",
-      "db_url": "/mongodbdriver",
-      "query_url": "/mongodbdriver?queries=",
-      "update_url": "/update-mongodb?queries=",
+      "db_url": "/mongodb",
+      "query_url": "/mongodb?queries=",
+      "update_url": "/mongodb-update?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
@@ -63,6 +64,7 @@
       "setup_file": "setup",
       "db_url": "/mysql-orm",
       "query_url": "/mysql-orm?queries=",
+      "update_url": "/mysql-orm-update?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
@@ -82,7 +84,7 @@
       "setup_file": "setup",
       "db_url": "/mysql",
       "query_url": "/mysql?queries=",
-      "update_url": "/update?queries=",
+      "update_url": "/mysql-update?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 285 - 213
frameworks/JavaScript/nodejs/hello.js

@@ -1,279 +1,351 @@
+/**
+ * Module dependencies.
+ */
+
 var cluster = require('cluster')
   , numCPUs = require('os').cpus().length
-  , windows = require('os').platform() == 'win32';
-
-if(cluster.isMaster) {
-  // Fork workers.
-  for (var i = 0; i < numCPUs; i++) {
-    cluster.fork();
-  }
-
-  cluster.on('exit', function(worker, code, signal) {
-    console.log('worker ' + worker.pid + ' died');
-  });
-
-  return;
-}
-
-var http = require('http')
+  , http = require('http')
   , url = require('url')
+  , Sequelize = require('sequelize')
+  , mysql = require('mysql')
   , async = require('async')
   , mongoose = require('mongoose')
   , conn = mongoose.connect('mongodb://localhost/hello_world')
-  , MongoClient = require('mongodb').MongoClient
-  , connMap = { user: 'benchmarkdbuser', password: 'benchmarkdbpass', database: 'hello_world', host: 'localhost' };
-
-if (!windows) {
-  var Mapper = require('mapper')  
-    , libmysql = require('mysql-libmysqlclient').createConnectionSync();
-    
-    Mapper.connect(connMap, {verbose: false, strict: false});
-    var World = Mapper.map("World", "id", "randomNumber")
-    libmysql.connectSync('localhost', 'benchmarkdbuser', 'benchmarkdbpass', 'hello_world');
-}
+  , MongoClient = require('mongodb').MongoClient;
 
+// MongoDB Raw Setup
 var collection = null;
-
 MongoClient.connect('mongodb://localhost/hello_world?maxPoolSize=5', function(err, db) {
   collection = db.collection('world');
 });
 
-// define model
-var Schema = mongoose.Schema
-  , ObjectId = Schema.ObjectId;
+// MySQL Raw Setup
+var connection = mysql.createConnection({
+  host     : 'localhost',
+  user     : 'benchmarkdbuser',
+  password : 'benchmarkdbpass',
+  database : 'hello_world'
+});
+connection.connect();
+
+// Mongoose Setup
+var WorldSchema = new mongoose.Schema({
+    id          : Number,
+    randomNumber: Number
+  }, {
+    collection: 'world'
+  }),
+  MWorld = conn.model('World', WorldSchema);
+
+// Sequelize Setup
+var sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', {
+  host: 'localhost',
+  dialect: 'mysql',
+  logging: false
+});
 
-var WorldSchema = new Schema({
-    id                           : Number
-  , randomNumber                 : Number
-}, { collection : 'world' });
-var MWorld = conn.model('World', WorldSchema);
+var World = sequelize.define('World', {
+  id: {
+    type: 'Sequelize.INTEGER'
+  },
+  randomNumber: {
+    type: 'Sequelize.INTEGER'
+  }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
+var Fortune = sequelize.define('Fortune', {
+  id: {
+    type: 'Sequelize.INTEGER'
+  },
+  message: {
+    type: 'Sequelize.STRING'
+  }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
 
+// Helper functions
 function getRandomNumber() {
   return Math.floor(Math.random() * 10000) + 1;
 }
 
+// Mongoose Query Functions
 function mongooseQuery(callback) {
-  MWorld.findOne({ id: getRandomNumber()}).exec(function (err, world) {
+  MWorld.findOne({
+    id: getRandomNumber()
+  }).exec(function (err, world) {
     callback(err, world);
   });
 }
 
+// MongoDB-Raw Query Functions
 function mongodbDriverQuery(callback) {
-  collection.findOne({ id: getRandomNumber()}, function(err, world) {
+  collection.findOne({
+    id: getRandomNumber()
+  }, function(err, world) {
+    world._id = undefined; // remove _id from query response
     callback(err, world);
   });
 }
 
 function mongodbDriverUpdateQuery(callback) {
-  collection.findAndModify({ id: getRandomNumber()}, [['_id','asc']], {$set: {randomNumber: getRandomNumber()}}, {}, function(err, world) {
-    callback(err, world);
+  collection.findAndModify({
+    id: getRandomNumber()
+  }, [['_id','asc']], {
+    $set: {randomNumber: getRandomNumber()}
+  }, {}, function(err, world) {
+    world.value._id = undefined; // remove _id from query response
+    callback(err, world.value);
   });
 }
 
+// Sequelize Query Functions
 function sequelizeQuery(callback) {
-  World.findById(getRandomNumber(), function (err, world) {
-    callback(null, world);
-  });
+  World.findOne({
+    where: {
+      id: Math.floor(Math.random() * 10000) + 1}
+    }
+  ).complete(callback);
 }
 
-http.createServer(function (req, res) {
-  // JSON response object
-  var hello = {message: "Hello, World!"};
-  var helloStr = "Hello, World!";
-  var path = url.parse(req.url).pathname;
-  
-  // mysql on windows is not supported
-  if (windows && (path.substr(0, 3) == '/my' || path == '/update')) {
-    path = '/doesntexist';
-  }
-
-  switch (path) {
-  case '/json':
-    // JSON Response Test
-    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
-    // Write JSON object to response
-    res.end(JSON.stringify(hello));
-    break;
-
-  case '/plaintext':
-    // JSON Response Test
-    res.writeHead(200, {'Content-Type': 'text/plain; charset=UTF-8'});
-    // Write JSON object to response
-    res.end(helloStr);
-    break;
-
-  case '/mongodbdriver':
-    // Database Test
-    var values = url.parse(req.url, true);
-    var queries = values.query.queries || 1;
-    var queryFunctions = new Array(queries);
 
-    for (var i = 0; i < queries; i += 1) {
-      queryFunctions[i] = mongodbDriverQuery;
+// MySQL-Raw Query Functions
+function mysqlQuery(callback) {
+  connection.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function (err, rows, fields) {
+    if (err) {
+      throw err;
     }
+    callback(null, rows[0]);
+  });
+}
 
-    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
-
-    async.parallel(queryFunctions, function(err, results) {
-      if (queries == 1) {
-        results = results[0];
+function mysqlUpdateQuery(callback) {
+  connection.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function (err, rows, fields) {
+    if (err) {
+      throw err;
+    }
+    rows[0].randomNumber = getRandomNumber();
+    var updateQuery = "UPDATE world SET randomNumber = " + rows[0].randomNumber + " WHERE id = " + rows[0]['id'];
+    connection.query(updateQuery, function (err, result) {
+      if (err) {
+        throw err;
       }
-      res.end(JSON.stringify(results));
+      callback(null, rows[0]);
     });
-    break;
-
-  case '/mongoose':
-    // Database Test
-    var values = url.parse(req.url, true);
-    var queries = values.query.queries || 1;
-    var queryFunctions = new Array(queries);
+  });
+} 
 
-    for (var i = 0; i < queries; i += 1) {
-      queryFunctions[i] = mongooseQuery;
-    }
+if(cluster.isMaster) {
+  // Fork workers.
+  for (var i = 0; i < numCPUs; i++) {
+    cluster.fork();
+  }
 
-    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
+  cluster.on('exit', function(worker, code, signal) {
+    console.log('worker ' + worker.pid + ' died');
+  });
 
-    async.parallel(queryFunctions, function(err, results) {
-      if (queries == 1) {
-        results = results[0];
-      }
-      res.end(JSON.stringify(results));
-    });
-    break;
+  return;
+} else {
+  http.createServer(function (req, res) {
+    // JSON response object
+    var hello = {message: "Hello, World!"};
+    var helloStr = "Hello, World!";
+    var path = url.parse(req.url).pathname;
+
+    switch (req.url) {
+      case '/json':
+        res.writeHead(200, {
+          'Content-Type': 'application/json',
+          'Server': 'Node'
+        });
+        res.end(JSON.stringify(hello));
+        break;
 
-  case '/mysql-orm':
+      case '/plaintext':
+        res.writeHead(200, {
+          'Content-Type': 'text/plain; charset=UTF-8',
+          'Server': 'Node'
+        });
+        res.end(helloStr);
+        break;
+    }
     var values = url.parse(req.url, true);
-    var queries = values.query.queries || 1;
-    var queryFunctions = new Array(queries);
+    var queries = isNaN(values.query.queries) ? 1 : parseInt(values.query.queries, 10);
+    queries = Math.min(Math.max(queries, 1), 500);
+    switch (values.pathname) {
+      // Raw MongoDB Routes
+      case '/mongodb':
+        var queryFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          queryFunctions.push(mongodbDriverQuery);
+        }
 
-    for (var i = 0; i < queries; i += 1) {
-      queryFunctions[i] = sequelizeQuery;
-    }
+        async.parallel(queryFunctions, function(err, results) {
+          if (!values.query.queries) {
+            results = results[0];
+          }
+          res.writeHead(200, {
+            'Content-Type': 'application/json',
+            'Server': 'Node'
+          });
+          res.end(JSON.stringify(results));
+        });
+        break;
 
-    res.writeHead(200, {'Content-Type': 'application/json'});
+      case '/mongodb-update':
+        var queryFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          queryFunctions.push(mongodbDriverUpdateQuery);
+        }
 
-    async.parallel(queryFunctions, function(err, results) {
-      if (queries == 1) {
-        results = results[0];
-      }
-      res.end(JSON.stringify(results));
-    });
-    break;
-
-  case '/mysql':
-    res.writeHead(200, {'Content-Type': 'application/json'});
-
-    function libmysqlQuery(callback) {
-      libmysql.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function (err, res) {
-        if (err) {
-	        throw err;
-	      }
-	
-	      res.fetchAll(function(err, rows) {
-      	  if (err) {
-      	    throw err;
-      	  }
-
-      	  res.freeSync();
-      	  callback(null, rows[0]);
+        async.parallel(queryFunctions, function(err, results) {
+          res.writeHead(200, {
+            'Content-Type': 'application/json',
+            'Server': 'Node'
+          });
+          res.end(JSON.stringify(results));
         });
-      });
-    } 
+        break;
 
-    var values = url.parse(req.url, true);
-    var queries = values.query.queries || 1;
-    var queryFunctions = new Array(queries);
-
-    for (var i = 0; i < queries; i += 1) {
-      queryFunctions[i] = libmysqlQuery;
-    }
-    async.parallel(queryFunctions, function(err, results) {
-      if (err) {
-        res.writeHead(500);
-        return res.end('MYSQL CONNECTION ERROR.');
-      }
-      if (queries == 1) {
-        results = results[0];
-      }
-      res.end(JSON.stringify(results));
-    });
-    break;
+      // Mongoose ORM Routes
+      case '/mongoose':
+        var queryFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          queryFunctions.push(mongooseQuery);
+        }
 
-  case '/update':
-    res.writeHead(200, {'Content-Type': 'application/json'});
+        async.parallel(queryFunctions, function(err, results) {
+          if (!values.query.queries) {
+            results = results[0];
+          }
+          res.writeHead(200, {
+            'Content-Type': 'application/json',
+            'Server': 'Node'
+          });
+          res.end(JSON.stringify(results));
+        });
+        break;
 
-    function libmysqlQuery(callback) {
-      libmysql.query("SELECT * FROM world WHERE id = " + getRandomNumber(), function (err, res) {
-        if (err) {
-          throw err;
+      case '/mongoose-update':
+        var selectFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          selectFunctions.push(mongooseQuery);
         }
-  
-        res.fetchAll(function(err, rows) {
-          if (err) {
-            throw err;
+
+        async.parallel(selectFunctions, function(err, worlds) {
+          var updateFunctions = [];
+
+          for (var i = 0; i < queries; i++) {
+            (function(i){
+              updateFunctions.push(function(callback){
+                worlds[i].randomNumber = Math.ceil(Math.random() * 10000);
+                MWorld.update({
+                  id: worlds[i]
+                }, {
+                  randomNumber: worlds[i].randomNumber
+                }, callback);
+              });
+            })(i);
           }
 
-          res.freeSync();
+          async.parallel(updateFunctions, function(err, updates) {
+            res.writeHead(200, {
+              'Content-Type': 'application/json',
+              'Server': 'Node'
+            });
+            res.end(JSON.stringify(worlds));
+          });
+        });
+        break;
+
+      // Sequelize (MySQL ORM) Routes
+      case '/mysql-orm':
+        var queryFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          queryFunctions.push(sequelizeQuery);
+        }
 
-          rows[0].randomNumber = getRandomNumber();
-          libmysql.query("UPDATE World SET randomNumber = " + rows[0].randomNumber + " WHERE id = " + rows[0]['id'], function (err, res) {
-            if (err) {
-              throw err;
-            }
-            callback(null, rows[0]);
+        async.parallel(queryFunctions, function(err, results) {
+          if (!values.query.queries) {
+            results = results[0];
+          }
+          res.writeHead(200, {
+            'Content-Type': 'application/json',
+            'Server': 'Node'
           });
+          res.end(JSON.stringify(results));
         });
-      });
-    } 
+        break;
 
-    var values = url.parse(req.url, true);
-    var queries = values.query.queries || 1;
-    if(queries < 1) {
-      queries = 1;
-    } else if(queries > 500) {
-      queries = 500;
-    }
-    var queryFunctions = new Array(queries);
+      case '/mysql-orm-update':
+        var selectFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          selectFunctions.push(sequelizeQuery);
+        }
 
-    for (var i = 0; i < queries; i += 1) {
-      queryFunctions[i] = libmysqlQuery;
-    }
-    async.parallel(queryFunctions, function(err, results) {
-      if (err) {
-        res.writeHead(500);
-        return res.end('MYSQL CONNECTION ERROR.');
-      }
-      res.end(JSON.stringify(results));
-    });
-    break;
+        async.parallel(selectFunctions, function(err, worlds) {
+          var updateFunctions = [];
 
-  case '/update-mongodb':
-    // Database Test
-    var values = url.parse(req.url, true);
-    var queries = values.query.queries || 1;
-    if (queries < 1) {
-      queries = 1;
-    } else if (queries > 500) {
-      queries = 500;
-    }
+          for (var i = 0; i < queries; i++) {
+            (function(i){
+              updateFunctions.push(function(callback){
+                worlds[i].randomNumber = Math.ceil(Math.random() * 10000);
+                worlds[i].save().complete(callback);
+              });
+            })(i);
+          }
 
-    var queryFunctions = new Array(queries);
+          async.parallel(updateFunctions, function(err, updates) {
+            res.writeHead(200, {
+              'Content-Type': 'application/json',
+              'Server': 'Node'
+            });
+            res.end(JSON.stringify(worlds));
+          });
+        });
+        break;
 
-    for (var i = 0; i < queries; i += 1) {
-      queryFunctions[i] = mongodbDriverUpdateQuery;
-    }
+      // Raw MongoDB Routes
+      case '/mysql':
+        var queryFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          queryFunctions.push(mysqlQuery);
+        }
 
-    res.writeHead(200, {'Content-Type': 'application/json; charset=UTF-8'});
+        async.parallel(queryFunctions, function(err, results) {
+          if (!values.query.queries) {
+            results = results[0];
+          }
+          res.writeHead(200, {
+            'Content-Type': 'application/json',
+            'Server': 'Node'
+          });
+          res.end(JSON.stringify(results));
+        });
+        break;
 
-    async.parallel(queryFunctions, function(err, results) {
-      res.end(JSON.stringify(results));
-    });
-    break;
+      case '/mysql-update':
+        var queryFunctions = [];
+        for (var i = 0; i < queries; i += 1) {
+          queryFunctions.push(mysqlUpdateQuery);
+        }
+        async.parallel(queryFunctions, function(err, results) {
+          res.writeHead(200, {
+            'Content-Type': 'application/json',
+            'Server': 'Node'
+          });
+          res.end(JSON.stringify(results));
+        });
+        break;
 
-  default:
-    // File not found handler
-    res.writeHead(501, {'Content-Type': 'text/plain; charset=UTF-8'});
-    res.end("NOT IMPLEMENTED");
-  }
-}).listen(8080);
+      default:
+        // File not found handler
+        res.writeHead(501, {'Content-Type': 'text/plain; charset=UTF-8'});
+        res.end("NOT IMPLEMENTED");
+      }
+    }).listen(8080);
+}

+ 5 - 5
frameworks/JavaScript/nodejs/package.json

@@ -3,11 +3,11 @@
   , "version": "0.0.1"
   , "private": true
   , "dependencies": {
-      "mongoose": "3.5.5" 
-    , "async": "0.2.5"
-    , "mysql-libmysqlclient": "1.5.2"
-    , "mapper": "0.2.4-pre"
-    , "mongodb": "1.3.0"
+      "mongoose": "4.0.1" 
+    , "async": "0.9.0"
+    , "mongodb": "2.0.27"
+    , "sequelize": "2.0.6"
+    , "mysql": "2.6.2"
   }
   , "main": "hello.js"
 }

+ 2 - 2
frameworks/JavaScript/nodejs/setup.sh

@@ -7,8 +7,8 @@ export NVM_HOME=${IROOT}/nvm
 # Used to avoid nvm's return 2 error.
 # Sourcing this functions if 0 is returned.
 source $NVM_HOME/nvm.sh || 0
-nvm install 0.10.8
-nvm use 0.10.8
+nvm install 0.12.2
+nvm use 0.12.2
 
 # update npm before app init
 npm install -g npm

+ 13 - 12
frameworks/Lua/lapis/config.lua

@@ -1,18 +1,19 @@
 local config
-do
-  local _obj_0 = require("lapis.config")
-  config = _obj_0.config
-end
+config = require("lapis.config").config
 config("development", function() end)
-return config("production", function()
+return config({
+  "production",
+  "development"
+}, function()
   port(80)
   num_workers(4)
   lua_code_cache("on")
-  return postgres({
-    backend = "pgmoon",
-    database = "hello_world",
-    user = "benchmarkdbuser",
-    password = "benchmarkdbpass",
-    host = "DBHOSTNAME"
-  })
+  logging(false)
+  return postgres(function()
+    backend("pgmoon")
+    database("hello_world")
+    user("benchmarkdbuser")
+    password("benchmarkdbpass")
+    return host("DBHOSTNAME")
+  end)
 end)

+ 8 - 8
frameworks/Lua/lapis/config.moon

@@ -2,14 +2,14 @@ import config from require "lapis.config"
 
 config "development", ->
 
-config "production", ->
+config {"production", "development"}, ->
   port 80
   num_workers 4
   lua_code_cache "on"
-  postgres {
-    backend: "pgmoon"
-    database: "hello_world"
-    user: "benchmarkdbuser"
-    password: "benchmarkdbpass"
-    host: "DBHOSTNAME"
-  }
+  logging false
+  postgres ->
+    backend "pgmoon"
+    database "hello_world"
+    user "benchmarkdbuser"
+    password "benchmarkdbpass"
+    host "DBHOSTNAME"

+ 1 - 2
frameworks/Lua/lapis/nginx.conf

@@ -1,6 +1,6 @@
     worker_processes auto;
 #    pid        /tmp/nginx.pid;
-    error_log stderr crit;
+    error_log stderr notice;
     #error_log /tmp/test.log error;
     env LAPIS_ENVIRONMENT;
     daemon off;
@@ -26,7 +26,6 @@
 
             location / {
                 default_type text/html;
-                set $_url "";
                 content_by_lua_file "loader.lua";
             }
 

+ 51 - 21
frameworks/Lua/openresty/app.lua

@@ -3,6 +3,12 @@ local mysql = mysql
 local encode = encode
 local random = math.random
 local min = math.min
+local insert = table.insert
+local sort = table.sort
+local template = require'resty.template'
+template.caching(false)
+-- Compile template, disable cache, enable plain text view to skip filesystem loading
+local view = template.compile([[<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>{% for _,f in ipairs(fortunes) do %}<tr><td>{{ f.id }}</td><td>{{ f.message }}</td></tr>{% end %}</table></body></html>]], nil, true)
 
 local mysqlconn = {
 	host = "DBHOSTNAME",
@@ -11,24 +17,48 @@ local mysqlconn = {
 	user = "benchmarkdbuser",
 	password = "benchmarkdbpass"
 }
-return function(ngx)
-	local db = mysql:new()
-	assert(db:connect(mysqlconn))
-	local num_queries = tonumber(ngx.var.arg_queries) or 1
-	-- May seem like a stupid branch, but since we know that
-	-- at a benchmark it will always be taken one way,
-	-- it doesn't matter. For me, after a small warmup, the performance
-	-- is identical to a version without the branch
-	-- http://wiki.luajit.org/Numerical-Computing-Performance-Guide
-	if num_queries == 1 then
-		ngx.print(encode(db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]))
-	else
-		local worlds = {}
-		num_queries = min(500, num_queries)
-		for i=1, num_queries do
-			worlds[#worlds+1] = db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]
-		end
-		ngx.print( encode(worlds) )
-	end
-	db:set_keepalive(0, 256)
-end
+return {
+    db = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        ngx.print(encode(db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]))
+        db:set_keepalive(0, 256)
+    end,
+    queries = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        local num_queries = tonumber(ngx.var.arg_queries) or 1
+        -- May seem like a stupid branch, but since we know that
+        -- at a benchmark it will always be taken one way,
+        -- it doesn't matter. For me, after a small warmup, the performance
+        -- is identical to a version without the branch
+        -- http://wiki.luajit.org/Numerical-Computing-Performance-Guide
+        if num_queries < 2 then
+            ngx.print(encode({db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]}))
+        else
+            local worlds = {}
+            num_queries = min(500, num_queries)
+            for i=1, num_queries do
+                worlds[#worlds+1] = db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]
+            end
+            ngx.print( encode(worlds) )
+        end
+        db:set_keepalive(0, 256)
+    end,
+    fortunes = function(ngx)
+        local db = mysql:new()
+        assert(db:connect(mysqlconn))
+        local fortunes = db:query('SELECT * FROM Fortune')
+        insert(fortunes, {
+            id = 0,
+            message = "Additional fortune added at request time."
+        })
+        sort(fortunes, function(a, b)
+            return a.message < b.message
+        end)
+        local res = view{fortunes=fortunes}
+        ngx.header['Content-Length'] = #res
+        ngx.print(res)
+        db:set_keepalive(0, 256)
+    end
+}

+ 2 - 1
frameworks/Lua/openresty/benchmark_config.json

@@ -5,7 +5,8 @@
       "setup_file": "setup",
       "json_url": "/json",
       "db_url": "/db",
-      "query_url": "/db?queries=",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",

+ 3 - 1
frameworks/Lua/openresty/install.sh

@@ -1,3 +1,5 @@
 #!/bin/bash
 
-fw_depends lua nginx openresty 
+fw_depends lua openresty
+
+sudo luarocks install --server=http://rocks.moonscript.org lua-resty-template

+ 11 - 2
frameworks/Lua/openresty/nginx.conf

@@ -9,7 +9,7 @@ http {
     resolver 127.0.0.1;
     access_log off;
     lua_package_path 'CWD/?.lua;;';
-    init_by_lua 'jit.opt.start("minstitch=10"); require "resty.core" encode = require("cjson").encode mysql = require("resty.mysql")';
+    init_by_lua 'jit.opt.start("minstitch=10"); require "resty.core" encode = require("cjson").encode mysql = require("resty.mysql") app = require("app")';
     server {
         listen       8080;
         location /plaintext {
@@ -21,8 +21,17 @@ http {
             default_type "application/json";
             content_by_lua 'ngx.print(encode({message = "Hello, World!"}))';
         }
+        location /fortunes {
+            default_type "text/html; charset=UTF-8";
+            content_by_lua 'app.fortunes(ngx)';
+        }
+        location /db {
+            default_type "application/json";
+            content_by_lua 'app.db(ngx)';
+        }
         location / {
-            content_by_lua 'require("app")(ngx)';
+            default_type "application/json";
+            content_by_lua 'app.queries(ngx)';
         }
     }
 }

+ 1 - 1
frameworks/PHP/php-laravel/app/config/session.php

@@ -16,7 +16,7 @@ return array(
 	|
 	*/
 
-	'driver' => 'file',
+	'driver' => 'array',
 
 	/*
 	|--------------------------------------------------------------------------

+ 25 - 4
frameworks/PHP/php-laravel/deploy/nginx.conf

@@ -1,7 +1,9 @@
 worker_processes  8;
 
 events {
-    worker_connections  1024;
+    worker_connections 2048;
+	multi_accept on;
+	use epoll;
 }
 
 http {
@@ -9,8 +11,27 @@ http {
     default_type  application/octet-stream;
     access_log off;
 
-    sendfile        on;
-    keepalive_timeout  65;
+    sendfile on;
+    tcp_nopush on;
+    tcp_nodelay on;
+    keepalive_timeout 65;
+	
+    open_file_cache max=2000 inactive=20s;
+    open_file_cache_valid 60s;
+    open_file_cache_min_uses 5;
+    open_file_cache_errors off; 
+
+    #FastCGI optimizations
+    fastcgi_buffers 256 16k;
+    fastcgi_buffer_size 128k;
+    fastcgi_connect_timeout 30s;
+    fastcgi_send_timeout 60s;
+    fastcgi_read_timeout 60s;
+    fastcgi_busy_buffers_size 256k;
+    fastcgi_temp_file_write_size 256k;
+    reset_timedout_connection on;
+    server_names_hash_bucket_size 100;
+	
 
     upstream fastcgi_backend {
         server 127.0.0.1:9001;
@@ -39,4 +60,4 @@ http {
             include        /home/vagrant/FrameworkBenchmarks/installs/nginx/conf/fastcgi_params;
         }
     }
-}
+}

+ 2 - 1
frameworks/PHP/php-laravel/install.sh

@@ -8,4 +8,5 @@ fw_depends php nginx composer
 ${PHP_HOME}/bin/php ${COMPOSER_HOME}/composer.phar install \
   --no-interaction --working-dir ${TROOT} \
   --no-progress --optimize-autoloader 
-  
+php artisan optimize --force
+  

+ 38 - 0
frameworks/Python/klein/README.md

@@ -0,0 +1,38 @@
+# Twisted Klein Benchmark Test
+
+This is the Klein portion of a [benchmarking tests suite](../../) 
+comparing a variety of web development platforms.
+
+The information below is specific to Klein. For further guidance, 
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/). 
+Also note that there is additional information provided in 
+the [Python README](../).
+
+## Description
+
+Klein framework (https://github.com/twisted/klein)
+
+## Infrastructure Software
+
+### Server
+
+* gunicorn+meinheld on CPython
+* Tornado on PyPy
+
+## Test Paths & Sources
+
+All of the test implementations are located within a single file ([app.py](app.py)).
+
+* [JSON Serialization](app.py): "/json"
+* [Single Database Query](app.py): "/db"
+* [Multiple Database Queries](app.py): "/queries?queries=5"
+* [Fortunes](app.py): "/fortune"
+* [Database Updates](app.py): "/updates?queries=5"
+* [Plaintext](app.py): "/plaintext"
+
+## Get Help
+
+### Resources
+
+* [Klein Source Code](https://github.com/twisted/klein)
+

+ 123 - 0
frameworks/Python/klein/app.py

@@ -0,0 +1,123 @@
+# -*- coding: utf-8 -*-
+
+import os
+import sys
+import json
+
+import bleach
+
+from random import randint
+from functools import partial
+from operator import attrgetter
+
+from klein import Klein, run, route
+
+from jinja2 import Environment, PackageLoader
+
+from sqlalchemy.ext.declarative import declarative_base
+from sqlalchemy import create_engine, Column
+from sqlalchemy.types import String, Integer, Unicode
+from sqlalchemy.orm import sessionmaker
+
+if sys.version_info[0] == 3:
+    xrange = range
+
+DBDRIVER = 'mysql'
+DBHOSTNAME = os.environ.get('DBHOST', 'localhost')
+DATABASE_URI = '%s://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world?charset=utf8' % (DBDRIVER, DBHOSTNAME)
+
+Base = declarative_base()
+db_engine = create_engine(DATABASE_URI)
+Session = sessionmaker(bind=db_engine)
+db_session = Session()
+
+env = Environment(loader=PackageLoader("app", "templates"))
+
+app = Klein()
+
+class Fortune(Base):
+    __tablename__ = "Fortune"
+    id = Column(Integer, primary_key=True)
+    message = Column(String)
+
+    def serialize(self):
+        return {
+            'id': self.id,
+            'randomNumber': self.randomNumber,
+        }
+
+class World(Base):
+    __tablename__ = "World"
+    id = Column(Integer, primary_key=True)
+    randomNumber = Column(Integer)
+    def serialize(self):
+        return {
+            'id': self.id,
+            'randomNumber': self.randomNumber,
+        }
+
+def getQueryNum(queryString):
+    try:
+        num_queries = int(queryString)
+        if num_queries < 1:
+            return 1
+        if num_queries > 500:
+            return 500
+        return num_queries
+    except ValueError:
+         return 1
+
[email protected]("/plaintext")
+def plaintext(request):
+	request.setHeader("Content-Type", "text/plain; charset=UTF-8")
+	return "Hello, World!"
+
[email protected]("/json")
+def jsonHandler(request):
+	request.setHeader("Content-Type", "application/json; charset=UTF-8")
+	return json.dumps({"message": "Hello, World!"})
+
[email protected]("/db")
+def db(request):
+	request.setHeader("Content-Type", "application/json; charset=UTF-8")	
+	wid = randint(1, 10000)
+	world = db_session.query(World).get(wid).serialize() 
+	return json.dumps(world)
+
[email protected]("/queries")
+def queries(request):
+	request.setHeader("Content-Type", "application/json; charset=UTF-8")	
+	num_queries = getQueryNum(request.args.get("queries")[0])
+	rp = partial(randint, 1, 10000)
+	get = db_session.query(World).get
+	worlds = [get(rp()).serialize() for _ in xrange(num_queries)]
+	return json.dumps(worlds)
+
[email protected]("/updates")
+def updates(request):
+	request.setHeader("Content-Type", "application/json; charset=UTF-8")
+	num_queries = getQueryNum(request.args.get("queries")[0])
+	worlds = []
+	rp = partial(randint, 1, 10000)
+	ids = [rp() for _ in xrange(num_queries)]
+	ids.sort()
+	for id in ids:
+		world = db_session.query(World).get(id)
+		world.randomNumber = rp()
+		worlds.append(world.serialize())
+	db_session.commit()
+	return json.dumps(worlds)
+
[email protected]("/fortune")
+def fortune(request):
+	request.setHeader("Content-Type", "text/html; charset=UTF-8")
+	fortunes = db_session.query(Fortune).all()
+	fortunes.append(Fortune(id=0, message="Additional fortune added at request time."))
+	fortunes.sort(key=attrgetter("message"))
+	for f in fortunes:
+		f.message = bleach.clean(f.message)
+	template = env.get_template("fortunes.html")
+	return template.render(fortunes=fortunes)
+
+if __name__ == "__main__":
+    app.run("0.0.0.0", 8080)

+ 27 - 0
frameworks/Python/klein/benchmark_config.json

@@ -0,0 +1,27 @@
+{
+  "framework": "klein",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "MySQL",
+      "framework": "Twisted Klein",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "Twisted Web",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Twisted Klein",
+      "notes": "CPython 2.7"
+    }
+  }]
+}

+ 19 - 0
frameworks/Python/klein/install.sh

@@ -0,0 +1,19 @@
+#!/bin/bash
+
+export PY2_ROOT=$IROOT/py2
+export PY2=$PY2_ROOT/bin/python
+export PY2_PIP=$PY2_ROOT/bin/pip
+
+export PY3_ROOT=$IROOT/py3
+export PY3=$PY3_ROOT/bin/python3
+export PY3_PIP=$PY3_ROOT/bin/pip3
+
+mkdir -p $IROOT/.pip_cache
+export PIP_DOWNLOAD_CACHE=$IROOT/.pip_cache
+
+fw_depends python2 python3
+
+$PY2_PIP install --install-option="--prefix=${PY2_ROOT}" -r $TROOT/requirements.txt
+
+$PY3_PIP install --install-option="--prefix=${PY3_ROOT}" -r $TROOT/requirements.txt
+

+ 6 - 0
frameworks/Python/klein/requirements.txt

@@ -0,0 +1,6 @@
+klein==15.0.0
+
+bleach==1.4.1
+mysqlclient==1.3.6
+SQLAlchemy==0.9.9
+jinja2==2.7.3

+ 6 - 0
frameworks/Python/klein/setup.sh

@@ -0,0 +1,6 @@
+#!/bin/bash
+
+export PY2_ROOT=$IROOT/py2
+export PY2=$PY2_ROOT/bin/python
+
+$PY2 app.py &

+ 20 - 0
frameworks/Python/klein/templates/fortunes.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Fortunes</title>
+    </head>
+    <body>
+        <table>
+            <tr>
+                <th>id</th>
+                <th>message</th>
+            </tr>
+            {%for fortune in fortunes %}
+                <tr>
+                    <td>{{ fortune.id }}</td>
+                    <td>{{ fortune.message }}</td>
+                </tr>
+            {% endfor %}
+        </table>
+    </body>
+</html>

+ 6 - 1
frameworks/Python/pyramid/create_database.py

@@ -1,11 +1,16 @@
 import codecs
+import os
 from frameworkbenchmarks.models import DBSession
 
+FWROOT = os.environ.get('FWROOT', '../../..')
+
 if __name__ == "__main__":
     """
     Initialize database
     """
-    with codecs.open('../config/create-postgres.sql', 'r', encoding='utf-8') as fp:
+    with codecs.open('%s/config/create-postgres.sql' % FWROOT,
+                     'r',
+                     encoding='utf-8') as fp:
         sql = fp.read()
     DBSession.execute(sql)
     DBSession.commit()

+ 1 - 1
frameworks/Python/pyramid/frameworkbenchmarks/tests.py

@@ -56,7 +56,7 @@ class FunctionalTests(unittest.TestCase):
         res = self._get('/queries?queries=999')
         self.assertEqual(len(json.loads(self._str_compat(res.body))), 500)
 
-    def test_queries_999(self):
+    def test_queries_10(self):
         """
         /queries?queries=10 objects
         """

+ 5 - 3
frameworks/Python/pyramid/frameworkbenchmarks/views.py

@@ -5,6 +5,7 @@ Test views, per the spec here:
 
 from random import randint
 from pyramid.view import view_config
+from pyramid.response import Response
 from frameworkbenchmarks.models import DBSession, World, Fortune
 
 
@@ -91,7 +92,8 @@ def test_6(request):
     """
     Test type 6: Plaintext
     """
-    response = request.response
-    response.text = u"Hello, World!" # py2k/3k
-    response.content_type = "text/plain"
+    response = Response(
+        body=b'Hello, World!',
+        content_type='text/plain',
+        )
     return response

+ 1 - 1
frameworks/Python/turbogears/app.py

@@ -84,7 +84,7 @@ class RootController(TGController):
         fortunes.sort(key=attrgetter("message"))
         for f in fortunes:
             f.message = bleach.clean(f.message)
-            template = env.get_template("fortunes.html")
+        template = env.get_template("fortunes.html")
         return template.render(fortunes=fortunes)
 
 config = AppConfig(minimal=True, root_controller=RootController())

+ 8 - 0
frameworks/Scala/colossus/.gitignore

@@ -0,0 +1,8 @@
+target/
+project/target
+bin/
+logs/
+.cache
+.classpath
+.project
+/bin/

+ 30 - 0
frameworks/Scala/colossus/README.md

@@ -0,0 +1,30 @@
+#colossus Benchmarking Test
+
+### JSON Encoding Test
+
+* [JSON test source](src/main/scala/example/Main.scala)
+
+### Plaintext Test
+
+* [JSON test source](src/main/scala/example/Main.scala)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java Oracle 1.8.0_25](http://www.oracle.com/technetwork/java/javase)
+* [colossus 0.6.1](http://tumblr.github.io/colossus/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:9007/json
+
+### Plaintext Test
+
+http://localhost:9007/plaintext
+
+## How to run
+sbt 'oneJar'
+
+java -jar target/scala-2.11/colossus*one-jar.jar
+

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

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

+ 14 - 0
frameworks/Scala/colossus/build.sbt

@@ -0,0 +1,14 @@
+name := """colossus-example"""
+
+version := "0.1.0"
+
+scalaVersion := "2.11.5"
+
+com.github.retronym.SbtOneJar.oneJarSettings
+
+mainClass in oneJar := Some("example.Main")
+
+libraryDependencies ++= Seq(
+  "com.tumblr" %% "colossus" % "0.6.1",
+  "net.liftweb" %% "lift-json" % "2.6-RC1"
+)

+ 3 - 0
frameworks/Scala/colossus/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends java8 sbt

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

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

+ 9 - 0
frameworks/Scala/colossus/setup.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+source $IROOT/java8.installed
+export SBT_HOME=${IROOT}/sbt
+
+${SBT_HOME}/bin/sbt 'oneJar'
+
+java -jar target/scala-2.11/colossus*one-jar.jar
+

+ 38 - 0
frameworks/Scala/colossus/src/main/scala/example/Main.scala

@@ -0,0 +1,38 @@
+package example
+
+import java.util.Date
+import java.text.SimpleDateFormat
+
+import colossus._
+import service._
+import protocols.http._
+import UrlParsing._
+import HttpMethod._
+
+import net.liftweb.json._
+import JsonDSL._
+
+object Main extends App {
+
+  implicit val io_system = IOSystem()
+
+  Service.become[Http]("sample", 9007) {
+    case request @ Get on Root / "json" => {
+      val json = ("message" -> "Hello, World!")
+      val sdf = new SimpleDateFormat("EEE, MMM d yyyy HH:MM:ss z")
+      val v = request.ok(compact(render(json)))
+        .withHeader("Content-Type", "application/json")
+        .withHeader("Server", "Colossus")
+        .withHeader("Date", sdf.format(new Date()))
+      Callback.successful(v)
+    }
+    case request @ Get on Root / "plaintext" => {
+      val sdf = new SimpleDateFormat("EEE, MMM d yyyy HH:MM:ss z")
+      val res = request.ok("Hello, World!")
+        .withHeader("Content-Type", "text/plain")
+        .withHeader("Server", "Colossus")
+        .withHeader("Date", sdf.format(new Date()))
+      Callback.successful(res)
+    }
+  }
+}

+ 3 - 0
frameworks/Scala/http4s/.gitignore

@@ -0,0 +1,3 @@
+target
+projet/target
+.cache

+ 26 - 0
frameworks/Scala/http4s/README.md

@@ -0,0 +1,26 @@
+#http4s Benchmarking Test
+
+### JSON Encoding Test
+
+* [JSON test source](src/main/scala/code/lib/WebServer.scala)
+
+## Infrastructure Software Versions
+The tests were run with:
+
+* [Java Oracle 1.8.0_25](http://www.oracle.com/technetwork/java/javase)
+* [http4s 0.6.2](http://http4s.org/)
+* [blaze 0.6.2](https://github.com/http4s/blaze/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/json
+
+### Plaintext Test
+
+http://localhost:8080/plaintext
+
+## How to run
+sbt 'oneJar'
+
+java -jar target/scala-2.11/http4s_2.11-1.0-SNAPSHOT-one-jar.jar

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

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

+ 17 - 0
frameworks/Scala/http4s/build.sbt

@@ -0,0 +1,17 @@
+name := "http4s"
+
+version := "1.0-SNAPSHOT"
+
+scalaVersion := "2.11.6"
+
+com.github.retronym.SbtOneJar.oneJarSettings
+
+libraryDependencies ++= Seq(
+	"org.http4s" %% "http4s-blazeserver" % "0.6.2",
+	"org.http4s" %% "http4s-dsl" % "0.6.2",
+	"org.http4s" %% "http4s-argonaut" % "0.6.2"
+)
+
+mainClass in oneJar := Some("WebServer")
+
+resolvers += "Bintray" at "http://dl.bintray.com/pchiusano/maven/"

+ 3 - 0
frameworks/Scala/http4s/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends java8 sbt

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

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

+ 9 - 0
frameworks/Scala/http4s/setup.sh

@@ -0,0 +1,9 @@
+#!/bin/bash
+
+source $IROOT/java8.installed
+export SBT_HOME=${IROOT}/sbt
+
+#${SBT_HOME}/bin/sbt compile
+${SBT_HOME}/bin/sbt 'oneJar'
+
+java -jar target/scala-2.11/http4s*one-jar.jar

+ 29 - 0
frameworks/Scala/http4s/src/main/scala/WebServer.scala

@@ -0,0 +1,29 @@
+import org.http4s._
+import org.http4s.server._
+import org.http4s.dsl._
+import org.http4s.argonaut._
+import org.http4s.server.blaze.BlazeBuilder
+import headers._
+
+import _root_.argonaut._, Argonaut._
+
+object WebServer extends App {
+
+  val service = HttpService {
+    case GET -> Root / "json" =>
+      val dateHeader = Date(DateTime(4))
+      Ok(Json("message" -> jString("Hello, World!")).asJson)
+        .withHeaders(dateHeader)
+        .withContentType(Some(`Content-Type`(MediaType.`application/json`)))
+    case GET -> Root / "plaintext" =>
+      val dateHeader = Date(DateTime(4))
+      Ok("Hello, World!")
+        .withHeaders(dateHeader)
+        .withContentType(Some(`Content-Type`(MediaType.`text/plain`)))
+  }
+
+  BlazeBuilder.bindHttp(8080)
+    .mountService(service, "/")
+    .run
+    .awaitShutdown()
+}

+ 2 - 1
frameworks/Scala/play2-scala/benchmark_config.json

@@ -18,7 +18,8 @@
         "notes": "", 
         "versus": "netty", 
         "port": "9000", 
-        "json_url": "/json"
+        "json_url": "/json",
+        "plaintext_url": "/plaintext"
       }, 
       "activate": {
         "display_name": "play2-scala-activate", 

+ 10 - 0
frameworks/Scala/play2-scala/play2-scala/app/controllers/Application.scala

@@ -9,4 +9,14 @@ object Application extends Controller {
     Ok(Json.obj("message" -> "Hello, World!"))
   }
 
+  def plaintext() = Action {
+    import java.util.Date
+    import java.text.SimpleDateFormat
+
+    val sdf = new SimpleDateFormat("EEE, MMM d yyyy HH:MM:ss z")
+    Ok("Hello, World!")
+      .withHeaders(
+        DATE -> sdf.format(new Date()),
+        SERVER -> "Play Framework 2.3.3")
+  }
 }

+ 1 - 0
frameworks/Scala/play2-scala/play2-scala/conf/routes

@@ -4,6 +4,7 @@
 
 # Home page
 GET     /json                           controllers.Application.json
+GET     /plaintext                      controllers.Application.plaintext
 
 # Map static resources from the /public folder to the /assets URL path
 GET     /assets/*file                   controllers.Assets.at(path="/public", file)

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

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-VERSION=20150103
+VERSION=20150412
 COMPILER=${IROOT}/urweb
 
 RETCODE=$(fw_exists $COMPILER)

+ 3 - 2
toolset/benchmark/benchmarker.py

@@ -715,13 +715,14 @@ class Benchmarker:
   # shutdown properly.
   ############################################################
   def __is_port_bound(self, port):
+    port = int(port)
     s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     try:
       # Try to bind to all IP addresses, this port
       s.bind(("", port))
       # If we get here, we were able to bind successfully,
       # which means the port is free.
-    except Exception:
+    except socket.error:
       # If we get an exception, it might be because the port is still bound
       # which would be bad, or maybe it is a privileged port (<1024) and we
       # are not running as root, or maybe the server is gone, but sockets are
@@ -732,7 +733,7 @@ class Benchmarker:
         # If we get here, we were able to connect to something, which means
         # that the port is still bound.
         return True
-      except Exception:
+      except socket.error:
         # An exception means that we couldn't connect, so a server probably
         # isn't still running on the port.
         pass

+ 10 - 6
toolset/benchmark/framework_test.py

@@ -256,7 +256,7 @@ class FrameworkTest:
       "%s: %s.sh and framework processes have terminated" % (self.name, self.setup_file))
 
     # Set a limit on total execution time of setup.sh
-    timeout = datetime.now() + timedelta(minutes = 20)
+    timeout = datetime.now() + timedelta(minutes = 105)
     time_remaining = timeout - datetime.now()
 
     # Need to print to stdout once every 10 minutes or Travis-CI will abort
@@ -274,9 +274,9 @@ class FrameworkTest:
     # output to the pipes. 
     #
     prefix = "Setup %s: " % self.name
-    while not (p.poll() 
-      or self.benchmarker.is_port_bound(self.port)
-      or time_remaining.total_seconds() < 0):
+    while (p.poll() is None
+      and not self.benchmarker.is_port_bound(self.port)
+      and not time_remaining.total_seconds() < 0):
       
       # The conditions above are slow to check, so 
       # we will delay output substantially if we only
@@ -301,6 +301,8 @@ class FrameworkTest:
 
       if (travis_timeout - datetime.now()).total_seconds() < 0:
         sys.stdout.write(prefix + 'Printing so Travis-CI does not time out\n')
+        sys.stdout.write(prefix + "Status: Poll: %s, Port %s bound: %s, Time Left: %s\n" % (
+          p.poll(), self.port, self.benchmarker.is_port_bound(self.port), time_remaining))
         sys.stdout.flush()
         travis_timeout = datetime.now() + timedelta(minutes = 5)
 
@@ -313,8 +315,10 @@ class FrameworkTest:
     # What's our return code? 
     # If setup.sh has terminated, use that code
     # Otherwise, detect if the port was bound
-    retcode = (p.poll() or 0 if self.benchmarker.is_port_bound(self.port) else 1)
-    if p.poll():
+    tee_output(prefix, "Status: Poll: %s, Port %s bound: %s, Time Left: %s\n" % (
+      p.poll(), self.port, self.benchmarker.is_port_bound(self.port), time_remaining))
+    retcode = (p.poll() if p.poll() is not None else 0 if self.benchmarker.is_port_bound(self.port) else 1)
+    if p.poll() is not None:
       tee_output(prefix, "%s.sh process exited naturally with %s\n" % (self.setup_file, p.poll()))
     elif self.benchmarker.is_port_bound(self.port):
       tee_output(prefix, "Bound port detected on %s\n" % self.port)

+ 0 - 9
toolset/setup/linux/frameworks/vertx.sh

@@ -1,9 +0,0 @@
-#!/bin/bash
-
-RETCODE=$(fw_exists ${IROOT}/vert.x-2.1.1.installed)
-[ ! "$RETCODE" == 0 ] || { return 0; }
-
-fw_get http://dl.bintray.com/vertx/downloads/vert.x-2.1.1.tar.gz?direct=true -O vert.x-2.1.1.tar.gz
-fw_untar vert.x-2.1.1.tar.gz
-
-touch ${IROOT}/vert.x-2.1.1.installed