Browse Source

Merge branch 'upstream'

Yun Zhi Lin 10 years ago
parent
commit
c6cc138a0f
100 changed files with 2352 additions and 698 deletions
  1. 5 0
      .travis.yml
  2. 2 3
      frameworks/C/duda/install.sh
  3. 1 1
      frameworks/C/duda/setup.sh
  4. 2 2
      frameworks/Crystal/moonshine/server.cr
  5. 7 0
      frameworks/D/vibed/.gitignore
  6. 34 0
      frameworks/D/vibed/README.md
  7. 26 0
      frameworks/D/vibed/benchmark_config.json
  8. 10 0
      frameworks/D/vibed/dub.json
  9. 11 0
      frameworks/D/vibed/dub.selections.json
  10. 3 0
      frameworks/D/vibed/install.sh
  11. 14 0
      frameworks/D/vibed/setup.sh
  12. 102 0
      frameworks/D/vibed/source/app.d
  13. 19 0
      frameworks/D/vibed/views/index.dt
  14. 5 0
      frameworks/Elixir/cowboy/.gitignore
  15. 1 0
      frameworks/Elixir/cowboy/README.md
  16. 24 0
      frameworks/Elixir/cowboy/benchmark_config.json
  17. 7 0
      frameworks/Elixir/cowboy/config/config.exs
  18. 3 0
      frameworks/Elixir/cowboy/install.sh
  19. 56 0
      frameworks/Elixir/cowboy/lib/hello.ex
  20. 20 0
      frameworks/Elixir/cowboy/mix.exs
  21. 13 0
      frameworks/Elixir/cowboy/setup.sh
  22. 3 2
      frameworks/Elixir/phoenix/.gitignore
  23. 7 3
      frameworks/Elixir/phoenix/benchmark_config.json
  24. 4 3
      frameworks/Elixir/phoenix/config/config.exs
  25. 24 4
      frameworks/Elixir/phoenix/config/dev.exs
  26. 12 3
      frameworks/Elixir/phoenix/config/prod.exs
  27. 7 0
      frameworks/Elixir/phoenix/config/prod.secret.exs
  28. 0 7
      frameworks/Elixir/phoenix/config/test.exs
  29. 2 1
      frameworks/Elixir/phoenix/lib/hello.ex
  30. 8 6
      frameworks/Elixir/phoenix/lib/hello/endpoint.ex
  31. 3 0
      frameworks/Elixir/phoenix/lib/hello/repo.ex
  32. 17 10
      frameworks/Elixir/phoenix/mix.exs
  33. 6 6
      frameworks/Elixir/phoenix/setup.sh
  34. 0 7
      frameworks/Elixir/phoenix/test/hello_test.exs
  35. 0 1
      frameworks/Elixir/phoenix/test/test_helper.exs
  36. 26 13
      frameworks/Elixir/phoenix/web/controllers/page_controller.ex
  37. 15 0
      frameworks/Elixir/phoenix/web/models/fortune.ex
  38. 0 11
      frameworks/Elixir/phoenix/web/models/repo.exs
  39. 15 0
      frameworks/Elixir/phoenix/web/models/world.ex
  40. 0 7
      frameworks/Elixir/phoenix/web/models/world.exs
  41. 5 5
      frameworks/Elixir/phoenix/web/router.ex
  42. 1 31
      frameworks/Elixir/phoenix/web/templates/layout/application.html.eex
  43. 0 1
      frameworks/Elixir/phoenix/web/templates/page/error.html.eex
  44. 1 0
      frameworks/Elixir/phoenix/web/templates/page/fortunes.html.eex
  45. 0 34
      frameworks/Elixir/phoenix/web/templates/page/index.html.eex
  46. 0 1
      frameworks/Elixir/phoenix/web/templates/page/not_found.html.eex
  47. 0 17
      frameworks/Elixir/phoenix/web/view.ex
  48. 4 3
      frameworks/Elixir/phoenix/web/views/error_view.ex
  49. 1 1
      frameworks/Elixir/phoenix/web/views/layout_view.ex
  50. 1 1
      frameworks/Elixir/phoenix/web/views/page_view.ex
  51. 73 0
      frameworks/Elixir/phoenix/web/web.ex
  52. 1 1
      frameworks/Erlang/cowboy/install.sh
  53. 2 3
      frameworks/Erlang/cowboy/setup.sh
  54. 1 1
      frameworks/Erlang/elli/install.sh
  55. 2 3
      frameworks/Erlang/elli/setup.sh
  56. 1 1
      frameworks/Java/grizzly-jersey/benchmark_config.json
  57. 15 13
      frameworks/Java/grizzly-jersey/src/main/java/hello/DbResource.java
  58. 10 5
      frameworks/Java/rapidoid/pom.xml
  59. 17 1
      frameworks/Java/rapidoid/src/main/java/hello/SimpleHttpProtocol.java
  60. 1 1
      frameworks/Java/servlet-dsl/benchmark_config.json
  61. 2 2
      frameworks/JavaScript/express/package.json
  62. 1 1
      frameworks/JavaScript/express/views/fortunes/index.jade
  63. 1 1
      frameworks/JavaScript/express/views/layout.jade
  64. 13 232
      frameworks/JavaScript/hapi/app.js
  65. 52 9
      frameworks/JavaScript/hapi/benchmark_config.json
  66. 83 0
      frameworks/JavaScript/hapi/create-server.js
  67. 128 0
      frameworks/JavaScript/hapi/handlers/mongoose.js
  68. 133 0
      frameworks/JavaScript/hapi/handlers/redis.js
  69. 117 0
      frameworks/JavaScript/hapi/handlers/sequelize-postgres.js
  70. 116 0
      frameworks/JavaScript/hapi/handlers/sequelize.js
  71. 31 0
      frameworks/JavaScript/hapi/helper.js
  72. 16 11
      frameworks/JavaScript/hapi/package.json
  73. 3 1
      frameworks/JavaScript/hapi/setup.sh
  74. 1 0
      frameworks/JavaScript/hapi/views/fortunes.hbs
  75. 0 21
      frameworks/JavaScript/hapi/views/fortunes.html
  76. 0 167
      frameworks/JavaScript/sailsjs/api/controllers/DatabaseQueryController.js
  77. 136 0
      frameworks/JavaScript/sailsjs/api/controllers/RedisController.js
  78. 154 0
      frameworks/JavaScript/sailsjs/api/controllers/SequelizeMySQLController.js
  79. 155 0
      frameworks/JavaScript/sailsjs/api/controllers/SequelizePostgresController.js
  80. 2 2
      frameworks/JavaScript/sailsjs/api/controllers/StaticTestController.js
  81. 20 0
      frameworks/JavaScript/sailsjs/api/services/helper.js
  82. 48 6
      frameworks/JavaScript/sailsjs/benchmark_config.json
  83. 20 7
      frameworks/JavaScript/sailsjs/config/routes.js
  84. 26 21
      frameworks/JavaScript/sailsjs/package.json
  85. 2 2
      frameworks/Lua/lapis/setup.sh
  86. 2 2
      frameworks/Lua/openresty/setup.sh
  87. 3 0
      frameworks/PHP/clancats/.bowerrc
  88. 12 0
      frameworks/PHP/clancats/.gitignore
  89. 72 0
      frameworks/PHP/clancats/app/App.php
  90. 24 0
      frameworks/PHP/clancats/app/config/database.config.php
  91. 27 0
      frameworks/PHP/clancats/app/config/main.config.php
  92. 107 0
      frameworks/PHP/clancats/app/config/router.config.php
  93. 33 0
      frameworks/PHP/clancats/app/controllers/BenchController.php
  94. 24 0
      frameworks/PHP/clancats/app/views/bench/fortune.php
  95. 28 0
      frameworks/PHP/clancats/benchmark_config.json
  96. 25 0
      frameworks/PHP/clancats/composer.json
  97. 43 0
      frameworks/PHP/clancats/deploy/nginx.conf
  98. 9 0
      frameworks/PHP/clancats/deploy/php-clancatsframework
  99. 1 0
      frameworks/PHP/clancats/deploy/php-fpm.pid
  100. 32 0
      frameworks/PHP/clancats/index.php

+ 5 - 0
.travis.yml

@@ -38,11 +38,13 @@ env:
     - "TESTDIR=Clojure/aleph"
     - "TESTDIR=Crystal/crystal-raw"
     - "TESTDIR=Crystal/moonshine"
+    - "TESTDIR=D/vibed"
     - "TESTDIR=Dart/dart"
     - "TESTDIR=Dart/dart-redstone"
     - "TESTDIR=Dart/dart-start"
     - "TESTDIR=Dart/dart-stream"
     - "TESTDIR=Elixir/phoenix"
+    - "TESTDIR=Elixir/cowboy"
     - "TESTDIR=Erlang/cowboy"
     - "TESTDIR=Erlang/elli"
     - "TESTDIR=Go/beego"
@@ -109,6 +111,7 @@ env:
     - "TESTDIR=PHP/php"
     - "TESTDIR=PHP/cygnite-php-framework"
     - "TESTDIR=PHP/codeigniter"
+    - "TESTDIR=PHP/clancats"
     - "TESTDIR=PHP/php-fatfree"
     - "TESTDIR=PHP/fuel"
     - "TESTDIR=PHP/kohana"
@@ -156,6 +159,7 @@ env:
     - "TESTDIR=Ruby/sinatra"
     - "TESTDIR=Rust/iron"
     - "TESTDIR=Rust/nickel"
+    - "TESTDIR=Rust/hyper"
     - "TESTDIR=Scala/akka-http"
     - "TESTDIR=Scala/colossus"
     - "TESTDIR=Scala/finagle"
@@ -168,6 +172,7 @@ env:
     - "TESTDIR=Scala/spray-es"
     - "TESTDIR=Scala/unfiltered"
     - "TESTDIR=Scala/http4s"
+    - "TESTDIR=Scala/finch"
     - "TESTDIR=Ur/urweb"
 
 before_install:

+ 2 - 3
frameworks/C/duda/install.sh

@@ -3,10 +3,9 @@
 RETCODE=$(fw_exists ${IROOT}/duda-0.23.installed)
 [ ! "$RETCODE" == 0 ] || { return 0; }
 
-fw_get http://duda.io/releases/duda-client/dudac-0.23.tar.gz -O dudac-0.23.tar.gz
-fw_untar dudac-0.23.tar.gz
+git clone https://github.com/monkey/dudac.git
 
-cd dudac-0.23
+cd dudac/
 
 ./dudac -r
 ./dudac -s

+ 1 - 1
frameworks/C/duda/setup.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 
-export DUDA_HOME=${IROOT}/dudac-0.23
+export DUDA_HOME=${IROOT}/dudac
 export PATH=${DUDA_HOME}:$PATH
 
 dudac -w $TROOT/webservice -p 2001 &

+ 2 - 2
frameworks/Crystal/moonshine/server.cr

@@ -104,9 +104,9 @@ app.get "/redis/fortunes", do |request|
   }
   data.push(additional_fortune)
 
-  data.sort! { |a, b|
+  data.sort! do |a, b|
     a[:message].to_s <=> b[:message].to_s
-  }
+  end
 
   # New builder for each request!
   html = HTML::Builder.new.build do

+ 7 - 0
frameworks/D/vibed/.gitignore

@@ -0,0 +1,7 @@
+.dub
+docs.json
+__dummy.html
+*.o
+*.obj
+*.dll
+*.exe

+ 34 - 0
frameworks/D/vibed/README.md

@@ -0,0 +1,34 @@
+# Vibe.D Benchmarking Test
+
+This is the Vibe.D portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+### JSON Encoding Test
+
+* [JSON test controller/view](source/app.d)
+
+### Data-Store/Database Mapping Test
+
+* [DB test controller/model](source/app.d)
+
+## Infrastructure Software Versions
+The tests were run with:
+* [Vibe.D v0.7.19](http://vibed.org/)
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/json
+
+### Plaintext Test
+
+http://localhost:8080/plaintext
+
+### Data-Store/Database Mapping Test
+
+MongoRaw:
+http://localhost:8080/db
+
+### Variable Query Test
+
+MongoDB Raw:
+http://localhost:8080/queries?queries=5

+ 26 - 0
frameworks/D/vibed/benchmark_config.json

@@ -0,0 +1,26 @@
+{
+  "framework": "vibed",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MongoDB",
+      "framework": "vibed",
+      "language": "D",
+      "orm": "Raw",
+      "platform": "D",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Vibe.D",
+      "notes": "",
+      "versus": "vibed"
+    }
+  }]
+}

+ 10 - 0
frameworks/D/vibed/dub.json

@@ -0,0 +1,10 @@
+{
+  "name": "fwb",
+  "description": "A simple vibe.d server application.",
+  "copyright": "Copyright © 2015, jin",
+  "authors": ["jin"],
+  "dependencies": {
+    "vibe-d": "~>0.7.19"
+  },
+  "versions": ["VibeDefaultMain"]
+}

+ 11 - 0
frameworks/D/vibed/dub.selections.json

@@ -0,0 +1,11 @@
+{
+  "fileVersion": 1,
+  "versions": {
+    "memutils": "0.3.5",
+    "vibe-d": "0.7.23",
+    "libevent": "2.0.1+2.0.16",
+    "openssl": "1.1.4+1.0.1g",
+    "libev": "5.0.0+4.04",
+    "libasync": "0.7.1"
+  }
+}

+ 3 - 0
frameworks/D/vibed/install.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+
+fw_depends dlang dub

+ 14 - 0
frameworks/D/vibed/setup.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+source $IROOT/dlang.installed
+source $IROOT/dub.installed
+
+sed -i 's|127.0.0.1|'"${DBHOST}"'|g' source/app.d
+
+# Clean any files from last run
+rm -f fwb
+rm -rf .dub
+
+dub build --force
+
+./fwb &

+ 102 - 0
frameworks/D/vibed/source/app.d

@@ -0,0 +1,102 @@
+import vibe.appmain;
+import vibe.d;
+import std.random;
+
+const worldSize = 10000;
+const fortunesSize = 100;
+const mongoUrl = "mongodb://127.0.0.1/";
+
+MongoClient mongo;
+MongoCollection worldCollection;
+MongoCollection fortunesCollection;
+
+shared static this()
+{
+  mongo = connectMongoDB( mongoUrl );
+  worldCollection = mongo.getCollection( "hello_world.World" );
+  fortunesCollection = mongo.getCollection( "hello_world.Fortunes" );
+
+  auto router = new URLRouter;
+  router.get("/plaintext", &plaintext);
+  router.get("/json", &json);
+  router.get("/db", &db);
+  router.get("/queries", &queries);
+  router.get("/generate-world", &generateWorld);
+  router.get("/generate-fortunes", &generateFortunes);
+  router.get("/", staticTemplate!"index.dt");
+
+  auto settings = new HTTPServerSettings;
+  settings.port = 8080;
+
+  listenHTTP(settings, router);
+}
+
+void json(HTTPServerRequest req, HTTPServerResponse res)
+{
+  auto helloWorld  = Json([
+    "message" : *new Json( "Hello, World!" )
+  ]);
+  res.writeJsonBody( helloWorld );
+}
+
+void generateWorld(HTTPServerRequest req, HTTPServerResponse res)
+{
+  try {
+    worldCollection.drop();
+  } catch( Exception error ) {}
+  for( auto i = 0 ; i < worldSize ; ++i ) {
+    worldCollection.insert([
+      "_id": i + 1,
+      "randomNumber": uniform( 0 , worldSize )
+    ]);
+  }
+  res.writeBody( "Generated" );
+}
+
+void generateFortunes(HTTPServerRequest req, HTTPServerResponse res)
+{
+  try {
+    fortunesCollection.drop();
+  } catch( Exception error ) {}
+  for( uint i = 0 ; i < worldSize ; ++i ) {
+    fortunesCollection.insert([
+      "_id": new Bson( i + 1 ),
+      "message": new Bson( to!string( uniform( 0 , fortunesSize ) ) )
+    ]);
+  }
+  res.writeBody( "Generated" );
+}
+
+void db(HTTPServerRequest req, HTTPServerResponse res)
+{
+  auto data = worldCollection.findOne([
+    "_id": uniform( 1 , worldSize + 1 )
+  ]); 
+  res.writeJsonBody( data );
+}
+
+void queries(HTTPServerRequest req, HTTPServerResponse res)
+{
+  auto count = 1;
+  try {
+    count = to!uint( req.query["queries"] );
+    if( !count ) {
+      count = 1;
+    } else if( count > 500 ) {
+      count = 500;
+    }
+  } catch( Exception error ) { }
+  
+  auto data = new Bson[ count ];
+  for( uint i = 0 ; i < count ; ++i ) {
+    data[i] = worldCollection.findOne([
+      "_id": uniform( 1 , worldSize + 1 )
+    ]);
+  }
+  res.writeJsonBody( data );
+}
+
+void plaintext(HTTPServerRequest req, HTTPServerResponse res)
+{
+  res.writeBody("Hello, World!");
+}

+ 19 - 0
frameworks/D/vibed/views/index.dt

@@ -0,0 +1,19 @@
+doctype html
+html
+  head
+    style a { display: block }
+  body
+    ul
+      li
+        a(href="/generate-world") generate world
+      li
+        a(href="/generate-fortunes") generate fortunes
+    ol
+      li
+        a(href="/json") json stringify
+      li
+        a(href="/db") single query
+      li
+        a(href="/queries?queries=5") multiple queries
+      li
+        a(href="/plaintext") plain text

+ 5 - 0
frameworks/Elixir/cowboy/.gitignore

@@ -0,0 +1,5 @@
+_build/
+rel/
+deps/
+erl_crash.dump
+*.ez

+ 1 - 0
frameworks/Elixir/cowboy/README.md

@@ -0,0 +1 @@
+# Elixir-cowboy

+ 24 - 0
frameworks/Elixir/cowboy/benchmark_config.json

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

+ 7 - 0
frameworks/Elixir/cowboy/config/config.exs

@@ -0,0 +1,7 @@
+use Mix.Config
+
+config :mysql,
+  username: "benchmarkdbuser",
+  password: "benchmarkdbpass",
+  database: "hello_world",
+  hostname: "localhost"

+ 3 - 0
frameworks/Elixir/cowboy/install.sh

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

+ 56 - 0
frameworks/Elixir/cowboy/lib/hello.ex

@@ -0,0 +1,56 @@
+defmodule Hello do
+
+  def start(_type, _args) do
+    dispatch = :cowboy_router.compile([
+
+      { :_,
+        [
+          {"/json", JsonHandler, []},
+          {"/plaintext", PlaintextHandler, []}
+      ]}
+    ])
+    { :ok, _ } = :cowboy.start_http(:http,
+                                    5000,
+                                   [{:port, 8080}],
+                                   [{ :env, [{:dispatch, dispatch}]}]
+                                   )
+  end
+end
+
+defmodule JsonHandler do
+  def init(_type, req, []) do
+    {:ok, req, :no_state}
+  end
+
+  def handle(request, state) do
+    Poison.encode!(%{message: "Hello, World!"})
+    { :ok, reply } = :cowboy_req.reply(200,
+      [{"content-type", "application/json"}],
+      Poison.encode!(%{:message => "Hello, World!"}),
+      request)
+    { :ok, reply, state }
+  end
+
+  def terminate(reason, request, state) do
+    :ok
+  end
+end
+
+defmodule PlaintextHandler do
+  def init(_type, req, []) do
+    {:ok, req, :no_state}
+  end
+
+  def handle(request, state) do
+    Poison.encode!(%{message: "Hello, World!"})
+    { :ok, reply } = :cowboy_req.reply(200,
+      [{"content-type", "text/plain"}],
+      "Hello, World!",
+      request)
+    { :ok, reply, state }
+  end
+
+  def terminate(reason, request, state) do
+    :ok
+  end
+end

+ 20 - 0
frameworks/Elixir/cowboy/mix.exs

@@ -0,0 +1,20 @@
+defmodule Hello.Mixfile do
+  use Mix.Project
+
+  def project do
+    [app: :hello,
+     version: "0.0.1",
+     elixir: "~> 1.0",
+     deps: deps]
+  end
+
+  def application do
+    [mod: {Hello, []},
+     applications: [:cowboy, :ranch, :poison]]
+  end
+
+  defp deps do
+    [{:cowboy, "~> 1.0"},
+     {:poison, "~> 1.4.0"}]
+  end
+end

+ 13 - 0
frameworks/Elixir/cowboy/setup.sh

@@ -0,0 +1,13 @@
+#!/bin/bash
+
+source $IROOT/elixir.installed
+
+rm -rf _build deps rel
+
+MIX_ENV=prod
+export MIX_ENV
+mix local.hex --force
+mix deps.get --force
+mix compile --force
+
+elixir --detached --no-halt -S mix

+ 3 - 2
frameworks/Elixir/phoenix/.gitignore

@@ -1,4 +1,5 @@
-/_build
-/deps
+_build/
+rel/
+deps/
 erl_crash.dump
 *.ez

+ 7 - 3
frameworks/Elixir/phoenix/benchmark_config.json

@@ -4,19 +4,23 @@
         "default": {
             "setup_file": "setup",
             "json_url": "/json",
+            "db_url": "/db",
+            "query_url": "/queries?queries=",
+            "fortune_url": "/fortune",
+            "update_url": "/update?queries=",
             "plaintext_url": "/plaintext",
             "port": 8080,
             "approach": "Realistic",
-            "classification": "Framework",
+            "classification": "Micro",
             "database": "Postgres",
             "framework": "Phoenix",
             "language": "elixir",
-            "orm": "etco",
+            "orm": "full",
             "platform": "Erlang/OTP",
             "webserver": "cowboy",
             "os": "Linux",
             "database_os": "Linux",
-            "display_name": "phoenix",
+            "display_name": "Phoenix",
             "notes": "",
             "versus": ""
         }

+ 4 - 3
frameworks/Elixir/phoenix/config/config.exs

@@ -8,10 +8,11 @@ use Mix.Config
 # Configures the endpoint
 config :hello, Hello.Endpoint,
   url: [host: "localhost"],
-  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx",
+  http: [port: 8080],
+  root: Path.expand(__DIR__),
   debug_errors: false,
-  pubsub: [adapter: Phoenix.PubSub.PG2]
-
+  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx",
+  pubsub: [name: Hello.PubSub, adapter: Phoenix.PubSub.PG2]
 
 # Configures Elixir's Logger
 config :logger, :console,

+ 24 - 4
frameworks/Elixir/phoenix/config/dev.exs

@@ -1,13 +1,33 @@
 use Mix.Config
 
+# For development, we disable any cache and enable
+# debugging and code reloading.
+#
+# The watchers configuration can be used to run external
+# watchers to your application. For example, we use it
+# with brunch.io to recompile .js and .css sources.
 config :hello, Hello.Endpoint,
-  url: [host: "localhost", port: 8080],
-  http: [port: System.get_env("PORT") || 8080],
+  http: [port: 8080],
   debug_errors: true,
+  code_reloader: true,
   cache_static_lookup: false
 
-# Enables code reloading for development
-config :phoenix, :code_reloader, true
+# Watch static and templates for browser reloading.
+config :hello, Hello.Endpoint,
+  live_reload: [
+    patterns: [
+      ~r{priv/static/.*(js|css|png|jpeg|jpg|gif)$},
+      ~r{web/views/.*(ex)$},
+      ~r{web/templates/.*(eex)$}
+    ]
+  ]
+
+config :hello, Hello.Repo,
+  adapter: Ecto.Adapters.MySQL,
+  username: "benchmarkdbuser",
+  password: "benchmarkdbpass",
+  database: "hello_world",
+  hostname: "localhost"
 
 # Do not include metadata nor timestamps in development logs
 config :logger, :console, format: "[$level] $message\n"

+ 12 - 3
frameworks/Elixir/phoenix/config/prod.exs

@@ -1,10 +1,17 @@
 use Mix.Config
 
 config :hello, Hello.Endpoint,
-  url: [host: "localhost", port: 8080],
+  url: [host: "0.0.0.0"],
   http: [port: 8080],
-  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx",
-  cache_static_lookup: false
+  cache_static_lookup: false,
+  server: true
+
+config :hello, Hello.Repo,
+  adapter: Ecto.Adapters.MySQL,
+  username: "benchmarkdbuser",
+  password: "benchmarkdbpass",
+  database: "hello_world",
+  hostname: "localhost"
 
 # ## SSL Support
 #
@@ -36,3 +43,5 @@ config :logger, level: :info
 #
 #     config :hello, Hello.Endpoint, server: true
 #
+
+import_config "prod.secret.exs"

+ 7 - 0
frameworks/Elixir/phoenix/config/prod.secret.exs

@@ -0,0 +1,7 @@
+use Mix.Config
+
+# In this file, we keep production configuration that
+# you likely want to automate and keep it away from
+# your version control system.
+config :hello, Hello.Endpoint,
+  secret_key_base: "Z18ZjzZslFpKd8HB41IljqMavPiOKVF9y1DIQ+S2Ytg7Op0EIauwJgd7mtRStssx"

+ 0 - 7
frameworks/Elixir/phoenix/config/test.exs

@@ -1,7 +0,0 @@
-use Mix.Config
-
-config :hello, Hello.Endpoint,
-  http: [port: System.get_env("PORT") || 4001]
-
-# Print only warnings and errors during test
-config :logger, level: :warn

+ 2 - 1
frameworks/Elixir/phoenix/lib/hello.ex

@@ -10,8 +10,9 @@ defmodule Hello do
       # Start the endpoint when the application starts
       supervisor(Hello.Endpoint, []),
       # Here you could define other workers and supervisors as children
+      # Start the Ecto repository
+      worker(Hello.Repo, [])
       # worker(Hello.Worker, [arg1, arg2, arg3]),
-      # worker(Hello.Repo, [])
     ]
 
     # See http://elixir-lang.org/docs/stable/elixir/Supervisor.html

+ 8 - 6
frameworks/Elixir/phoenix/lib/hello/endpoint.ex

@@ -3,14 +3,17 @@ defmodule Hello.Endpoint do
 
   # Serve at "/" the given assets from "priv/static" directory
   plug Plug.Static,
-    at: "/", from: :hello,
+    at: "/", from: :hello, gzip: false,
     only: ~w(css images js favicon.ico robots.txt)
 
-  plug Plug.Logger
-
   # Code reloading will only work if the :code_reloader key of
   # the :phoenix application is set to true in your config file.
-  plug Phoenix.CodeReloader
+  if code_reloading? do
+    plug Phoenix.LiveReloader
+    plug Phoenix.CodeReloader
+  end
+
+  plug Plug.Logger
 
   plug Plug.Parsers,
     parsers: [:urlencoded, :multipart, :json],
@@ -23,8 +26,7 @@ defmodule Hello.Endpoint do
   plug Plug.Session,
     store: :cookie,
     key: "_hello_key",
-    signing_salt: "DNlAnJ2o",
-    encryption_salt: "AOXxaZRq"
+    signing_salt: "DNlAnJ2o"
 
   plug :router, Hello.Router
 end

+ 3 - 0
frameworks/Elixir/phoenix/lib/hello/repo.ex

@@ -0,0 +1,3 @@
+defmodule Hello.Repo do
+    use Ecto.Repo, otp_app: :hello
+end

+ 17 - 10
frameworks/Elixir/phoenix/mix.exs

@@ -2,12 +2,14 @@ defmodule Hello.Mixfile do
   use Mix.Project
 
   def project do
-    [app: :hello,
-     version: "0.0.1",
-     elixir: "~> 1.0",
-     elixirc_paths: ["lib", "web"],
-     compilers: [:phoenix] ++ Mix.compilers,
-     deps: deps]
+   [app: :hello,
+    version: "0.0.1",
+    elixir: "~> 1.0",
+    elixirc_paths: elixirc_paths(Mix.env),
+    compilers: [:phoenix] ++ Mix.compilers,
+    build_embedded: Mix.env == :prod,
+    start_permanent: Mix.env == :prod,
+    deps: deps]
   end
 
   # Configuration for the OTP application
@@ -15,16 +17,21 @@ defmodule Hello.Mixfile do
   # Type `mix help compile.app` for more information
   def application do
     [mod: {Hello, []},
-     applications: [:phoenix, :cowboy, :logger, :postgrex, :ecto]]
+     applications: [:phoenix, :phoenix_ecto, :mariaex, :cowboy, :logger, :phoenix_html]]
   end
 
+  defp elixirc_paths(_), do: ["lib", "web"]
+
   # Specifies your project dependencies
   #
   # Type `mix help deps` for examples and options
   defp deps do
-    [{:phoenix, "~> 0.9.0"},
+    [{:phoenix, "~> 0.13.1"},
+     {:phoenix_ecto, "~> 0.4"},
+     {:mariaex, ">= 0.0.0"},
      {:cowboy, "~> 1.0"},
-     {:postgrex, "~> 0.6.0"},
-     {:ecto, "~> 0.2.5"}]
+     {:phoenix_html, "~> 1.0"},
+     {:phoenix_live_reload, "~> 0.4", only: :dev},
+     {:exrm, "~> 0.15.3"}]
   end
 end

+ 6 - 6
frameworks/Elixir/phoenix/setup.sh

@@ -2,14 +2,14 @@
 
 source $IROOT/elixir.installed
 
-sed -i 's|db_host: "localhost",|db_host: "${DBHOST}",|g' config/config.exs
+sed -i 's|hostname: "localhost"|hostname: "'${DBHOST}'"|g' config/prod.exs
 
-rm -rf _build deps
+rm -rf _build deps rel
 
+MIX_ENV=prod
+export MIX_ENV
 mix local.hex --force
-mix local.rebar --force
 mix deps.get --force
+mix compile --force
 
-MIX_ENV=prod mix compile.protocols --force
-MIX_ENV=prod elixir --detached -pa _build/$MIX_ENV/consolidated -S mix phoenix.server
-
+elixir --detached -S mix phoenix.server

+ 0 - 7
frameworks/Elixir/phoenix/test/hello_test.exs

@@ -1,7 +0,0 @@
-defmodule HelloTest do
-  use ExUnit.Case
-
-  test "the truth" do
-    assert 1 + 1 == 2
-  end
-end

+ 0 - 1
frameworks/Elixir/phoenix/test/test_helper.exs

@@ -1 +0,0 @@
-ExUnit.start

+ 26 - 13
frameworks/Elixir/phoenix/web/controllers/page_controller.ex

@@ -1,14 +1,14 @@
 defmodule Hello.PageController do
-  use Phoenix.Controller
+  use Hello.Web, :controller
+  alias Hello.World
+  alias Hello.Fortune
 
   plug :action
+  plug :scrub_params, "world" when action in [:create, :update]
+
 
   def index(conn, _params) do
-    json conn, %{
-      "TE Benchmarks\n" => "Started",
-      "DBHOST" => System.get_env("DBHOST"),
-      "DBPORT" => System.get_env("DBPORT"),
-    }
+    json conn, %{"TE Benchmarks\n" => "Started"}
   end
 
   # avoid namespace collision
@@ -17,22 +17,35 @@ defmodule Hello.PageController do
   end
 
   def db(conn, _params) do
-    :random.seed(:erlang.now)
-    id = :random.uniform(10000)
-    text conn, "TE Benchmarks\n"
+    json conn, Repo.get(World, :random.uniform(10000))
   end
 
   def queries(conn, _params) do
-    text conn, "TE Benchmarks\n"
+    q = case String.to_integer(_params["queries"]) do
+      x when x < 1    -> 1
+      x when x > 500  -> 500
+      x               -> x
+    end
+    json conn, Enum.map(1..q, fn _ -> Repo.get(World, :random.uniform(10000)) end)
   end
 
   def fortunes(conn, _params) do
-    text conn, "TE Benchmarks\n"
+    fortunes = List.insert_at(Repo.all(Fortune), 0, %Fortune{:id => 0, :message  => "Additional fortune added at request time."})
+    render conn, "fortunes.html", fortunes: Enum.sort(fortunes, fn f1, f2 -> f1.message < f2.message end)
   end
 
   def updates(conn, _params) do
-    text conn, "TE Benchmarks\n"
-  end
+    q = case String.to_integer(_params["queries"]) do
+      x when x < 1    -> 1
+      x when x > 500  -> 500
+      x               -> x
+    end
+    json conn, Enum.map(1..q, fn _ ->
+      w = Repo.get(World, :random.uniform(10000))
+      changeset = World.changeset(w, %{randomNumber: :random.uniform(10000)})
+      Repo.update(changeset)
+      w end)
+    end
 
   def plaintext(conn, _params) do
     text conn, "Hello, world!"

+ 15 - 0
frameworks/Elixir/phoenix/web/models/fortune.ex

@@ -0,0 +1,15 @@
+defmodule Hello.Fortune do
+  use Hello.Web, :model
+
+  schema "fortune" do
+    field :message, :string
+  end
+
+  @required_fields ~w(message)
+  @optional_fields ~w()
+
+  def changeset(model, params \\ nil) do
+    model
+    |> cast(params, @required_fields, @optional_fields)
+  end
+end

+ 0 - 11
frameworks/Elixir/phoenix/web/models/repo.exs

@@ -1,11 +0,0 @@
-defmodule Hello.Repo do
-  use Ecto.Repo, adapter: Ecto.Adapters.Postgres
-
-  def conf do
-    parse_url "ecto://username:password@host/database_name"
-  end
-
-  def priv do
-    app_dir(:hello, "priv/repo")
-  end
-end

+ 15 - 0
frameworks/Elixir/phoenix/web/models/world.ex

@@ -0,0 +1,15 @@
+defmodule Hello.World do
+  use Hello.Web, :model
+
+  schema "world" do
+    field :randomNumber, :integer
+  end
+
+  @required_fields ~w(randomNumber)
+  @optional_fields ~w()
+
+  def changeset(model, params \\ nil) do
+    model
+    |> cast(params, @required_fields, @optional_fields)
+  end
+end

+ 0 - 7
frameworks/Elixir/phoenix/web/models/world.exs

@@ -1,7 +0,0 @@
-defmodule Hello.User do
-  use Ecto.Model
-
-  schema "world" do
-    field :randomNumber, :integer
-  end
-end

+ 5 - 5
frameworks/Elixir/phoenix/web/router.ex

@@ -1,15 +1,15 @@
 defmodule Hello.Router do
-  use Phoenix.Router
+  use Hello.Web, :router
 
   pipeline :browser do
-    plug :accepts, ~w(html)
+    plug :accepts, ["html"]
     plug :fetch_session
     plug :fetch_flash
     plug :protect_from_forgery
   end
 
   pipeline :api do
-    plug :accepts, ~w(json)
+    plug :accepts, ["json"]
   end
 
   scope "/", Hello do
@@ -18,8 +18,8 @@ defmodule Hello.Router do
     get "/json", PageController, :_json
     get "/db", PageController, :db
     get "/queries", PageController, :queries
-    get "/fortunes", PageController, :fortunes
-    get "/updates", PageController, :updates
+    get "/fortune", PageController, :fortunes
+    get "/update", PageController, :updates
     get "/plaintext", PageController, :plaintext
     get "/", PageController, :index
   end

+ 1 - 31
frameworks/Elixir/phoenix/web/templates/layout/application.html.eex

@@ -1,31 +1 @@
-<!DOCTYPE html>
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge">
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <meta name="description" content="">
-    <meta name="author" content="">
-
-    <title>Hello Phoenix!</title>
-    <link rel="stylesheet" href="/css/phoenix.css">
-  </head>
-
-  <body>
-    <div class="container">
-      <div class="header">
-        <ul class="nav nav-pills pull-right">
-          <li><a href="http://www.phoenixframework.org/docs">Get Started</a></li>
-        </ul>
-        <span class="logo"></span>
-      </div>
-
-      <%= @inner %>
-
-      <div class="footer">
-        <p><a href="http://phoenixframework.org">phoenixframework.org</a></p>
-      </div>
-
-    </div> <!-- /container -->
-  </body>
-</html>
+<!DOCTYPE html><html lang="en"><head><title>Fortunes</title></head><body><%= @inner %></body></html>

+ 0 - 1
frameworks/Elixir/phoenix/web/templates/page/error.html.eex

@@ -1 +0,0 @@
-Something went wrong

+ 1 - 0
frameworks/Elixir/phoenix/web/templates/page/fortunes.html.eex

@@ -0,0 +1 @@
+<table><tr><th>id</th><th>message</th></tr><%= for f <- @fortunes do %><tr><td><%= f.id %></td><td><%= f.message %></td></tr><% end %></table>

+ 0 - 34
frameworks/Elixir/phoenix/web/templates/page/index.html.eex

@@ -1,34 +0,0 @@
-<div class="jumbotron">
-  <h2>Welcome to Phoenix!</h2>
-  <p class="lead">Phoenix is an Elixir Web Framework targeting full-featured, fault tolerant applications with realtime functionality.</p>
-</div>
-
-<div class="row marketing">
-  <div class="col-lg-6">
-    <h4>Resources</h4>
-    <ul>
-      <li>
-        <a href="http://hexdocs.pm/phoenix">Docs</a>
-      </li>
-      <li>
-        <a href="https://github.com/phoenixframework/phoenix">Source</a>
-      </li>
-    </ul>
-  </div>
-
-  <div class="col-lg-6">
-    <h4>Help</h4>
-    <ul>
-      <li>
-        <a href="https://github.com/phoenixframework/phoenix/issues?state=open">Issues</a>
-      </li>
-      <li>
-        <a href="irc://irc.freenode.net/elixir-lang">#elixir-lang on freenode IRC</a>
-      </li>
-      <li>
-        <a href="https://twitter.com/chris_mccord">@chris_mccord</a>
-      </li>
-    </ul>
-  </div>
-</div>
-

+ 0 - 1
frameworks/Elixir/phoenix/web/templates/page/not_found.html.eex

@@ -1 +0,0 @@
-The page you are looking for does not exist

+ 0 - 17
frameworks/Elixir/phoenix/web/view.ex

@@ -1,17 +0,0 @@
-defmodule Hello.View do
-  use Phoenix.View, root: "web/templates"
-
-  # The quoted expression returned by this block is applied
-  # to this module and all other views that use this module.
-  using do
-    quote do
-      # Import common functionality
-      import Hello.Router.Helpers
-
-      # Use Phoenix.HTML to import all HTML functions (forms, tags, etc)
-      use Phoenix.HTML
-    end
-  end
-
-  # Functions defined here are available to all other views/templates
-end

+ 4 - 3
frameworks/Elixir/phoenix/web/views/error_view.ex

@@ -1,5 +1,5 @@
 defmodule Hello.ErrorView do
-  use Hello.View
+  use Hello.Web, :view
 
   def render("404.html", _assigns) do
     "Page not found - 404"
@@ -9,8 +9,9 @@ defmodule Hello.ErrorView do
     "Server internal error - 500"
   end
 
-  # Render all other templates as 500
-  def render(_, assigns) do
+  # In case no render clause matches or no
+  # template is found, let's render it as 500
+  def template_not_found(_template, assigns) do
     render "500.html", assigns
   end
 end

+ 1 - 1
frameworks/Elixir/phoenix/web/views/layout_view.ex

@@ -1,3 +1,3 @@
 defmodule Hello.LayoutView do
-  use Hello.View
+  use Hello.Web, :view
 end

+ 1 - 1
frameworks/Elixir/phoenix/web/views/page_view.ex

@@ -1,3 +1,3 @@
 defmodule Hello.PageView do
-  use Hello.View
+  use Hello.Web, :view
 end

+ 73 - 0
frameworks/Elixir/phoenix/web/web.ex

@@ -0,0 +1,73 @@
+defmodule Hello.Web do
+  @moduledoc """
+  A module that keeps using definitions for controllers,
+  views and so on.
+
+  This can be used in your application as:
+
+      use Hello.Web, :controller
+      use Hello.Web, :view
+
+  Keep the definitions in this module short and clean,
+  mostly focused on imports, uses and aliases.
+  """
+
+  def model do
+    quote do
+      use Ecto.Model
+    end
+  end
+
+  def controller do
+    quote do
+      use Phoenix.Controller
+
+      # Alias the data repository and import query/model functions
+      alias Hello.Repo
+      import Ecto.Model
+      import Ecto.Query
+
+      # Import URL helpers from the router
+      import Hello.Router.Helpers
+    end
+  end
+
+  def view do
+    quote do
+      use Phoenix.View, root: "web/templates"
+
+      # Import convenience functions from controllers
+      import Phoenix.Controller, only: [get_csrf_token: 0, get_flash: 2, view_module: 1]
+
+      # Import URL helpers from the router
+      import Hello.Router.Helpers
+
+      # Import all HTML functions (forms, tags, etc)
+      use Phoenix.HTML
+    end
+  end
+
+  def router do
+    quote do
+      use Phoenix.Router
+    end
+  end
+
+
+  def channel do
+    quote do
+      use Phoenix.Channel
+      # Alias the data repository and import query/model functions
+      alias Hello.Repo
+      import Ecto.Model
+      import Ecto.Query, only: [from: 2]
+    end
+  end
+
+  @doc """
+  When used, dispatch to the appropriate controller/view/etc.
+  """
+  defmacro __using__(which) when is_atom(which) do
+    apply(__MODULE__, which, [])
+  end
+end

+ 1 - 1
frameworks/Erlang/cowboy/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends erlang rebar
+fw_depends erlang

+ 2 - 3
frameworks/Erlang/cowboy/setup.sh

@@ -1,11 +1,10 @@
 #!/bin/bash
 
 source $IROOT/erlang.installed
-source $IROOT/rebar.installed
 
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/hello_world_app.erl
 
 rm -rf deps/* ebin/*
-$REBAR_HOME/rebar get-deps
-$REBAR_HOME/rebar compile
+rebar get-deps
+rebar compile
 erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s hello_world -noshell -detached

+ 1 - 1
frameworks/Erlang/elli/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends erlang rebar
+fw_depends erlang

+ 2 - 3
frameworks/Erlang/elli/setup.sh

@@ -1,11 +1,10 @@
 #!/bin/bash
 
 source $IROOT/erlang.installed
-source $IROOT/rebar.installed
 
 sed -i 's|"benchmarkdbpass", ".*", 3306|"benchmarkdbpass", "'"${DBHOST}"'", 3306|g' src/elli_bench_sup.erl
 
 rm -rf deps/* ebin/*
-$REBAR_HOME/rebar get-deps
-$REBAR_HOME/rebar compile
+rebar get-deps
+rebar compile
 erl -pa ebin deps/*/ebin +sbwt very_long +swt very_low -s elli_bench -noshell -detached

+ 1 - 1
frameworks/Java/grizzly-jersey/benchmark_config.json

@@ -4,7 +4,7 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
-      "db_url": "/db",
+      "db_url": "/db?single=true",
       "query_url": "/db?queries=",
       "fortune_url": "/fortunes",
       "port": 8080,

+ 15 - 13
frameworks/Java/grizzly-jersey/src/main/java/hello/DbResource.java

@@ -11,14 +11,12 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.Future;
 import java.util.concurrent.ThreadLocalRandom;
 
-import javax.ws.rs.DefaultValue;
 import javax.ws.rs.GET;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.Context;
 
-import org.hibernate.IdentifierLoadAccess;
 import org.hibernate.Session;
 import org.hibernate.SessionFactory;
 
@@ -35,15 +33,12 @@ public class DbResource {
   
   @GET
   @Produces(APPLICATION_JSON + "; charset=utf-8")
-  public Object db(@QueryParam("queries") String queriesParam)
+  public Object db(@QueryParam("queries") String queryParam, @QueryParam("single") boolean isSingle)
       throws ExecutionException, InterruptedException {
 
-    final int queries = getQueries(queriesParam);
+    final int queries = getQueries(queryParam);
     final World[] worlds = new World[queries];
     final Random random = ThreadLocalRandom.current();
-    final Session session = sessionFactory.openSession();
-    session.setDefaultReadOnly(true);
-    final IdentifierLoadAccess accessor = session.byId(World.class);
 
     Map<Integer, Future<World>> futureWorlds = new ConcurrentHashMap<>();
     for (int i = 0; i < queries; i++) {
@@ -51,7 +46,14 @@ public class DbResource {
         new Callable<World>() {
           @Override
           public World call() throws Exception {
-            return (World) accessor.load(random.nextInt(DB_ROWS) + 1);
+            Session session = sessionFactory.openSession();
+            session.setDefaultReadOnly(true);
+
+            try {
+              return (World) session.byId(World.class).load(random.nextInt(DB_ROWS) + 1);
+            } finally {
+              session.close();
+            }
           }
         }
       ));
@@ -61,16 +63,16 @@ public class DbResource {
       worlds[i] = futureWorlds.get(i).get();
     }
 
-    return queries == 1 ? worlds[0] : worlds;
+    return isSingle ? worlds[0] : worlds;
   }
 
   private int getQueries(String proto) {
     int result = 1;
     try {
-      result = Integer.parseInt(proto);
-    } catch (NumberFormatException e) {
-      e.printStackTrace();
-    }
+      if (proto != null && !proto.trim().isEmpty()) {
+        result = Integer.parseInt(proto);
+      }
+    } catch (NumberFormatException e) {/* by test contract */}
 
     return Math.min(500, Math.max(1, result));
   }

+ 10 - 5
frameworks/Java/rapidoid/pom.xml

@@ -18,11 +18,16 @@
             <artifactId>rapidoid-http</artifactId>
             <version>3.0.0</version>
         </dependency>
-        <dependency>
-            <groupId>org.rapidoid</groupId>
-            <artifactId>rapidoid-json</artifactId>
-            <version>3.0.0</version>
-        </dependency>
+	<dependency>
+		<groupId>com.fasterxml.jackson.core</groupId>
+		<artifactId>jackson-databind</artifactId>
+		<version>2.6.0-rc2</version>
+	</dependency>
+	<dependency>
+		<groupId>com.fasterxml.jackson.module</groupId>
+		<artifactId>jackson-module-afterburner</artifactId>
+		<version>2.6.0-rc2</version>
+	</dependency>
     </dependencies>
 
 	<build>

+ 17 - 1
frameworks/Java/rapidoid/src/main/java/hello/SimpleHttpProtocol.java

@@ -31,6 +31,9 @@ import org.rapidoid.net.impl.RapidoidHelper;
 import org.rapidoid.util.Dates;
 import org.rapidoid.wrap.BoolWrap;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
+
 public class SimpleHttpProtocol implements Protocol {
 
 	private static final byte[] HTTP_200_OK = "HTTP/1.1 200 OK\r\n".getBytes();
@@ -70,6 +73,14 @@ public class SimpleHttpProtocol implements Protocol {
 
 	private static final HttpParser HTTP_PARSER = new HttpParser();
 
+	public static final ObjectMapper MAPPER = mapper();
+
+	private static ObjectMapper mapper() {
+		ObjectMapper mapper = new ObjectMapper();
+		mapper.registerModule(new AfterburnerModule());
+		return mapper;
+	}
+
 	public void process(Channel ctx) {
 		if (ctx.isInitial()) {
 			return;
@@ -153,7 +164,12 @@ public class SimpleHttpProtocol implements Protocol {
 
 		int posBefore = output.size();
 
-		ctx.writeJSON(new Message("Hello, World!"));
+		Message msg = new Message("Hello, World!");
+		try {
+			MAPPER.writeValue(output.asOutputStream(), msg);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
 
 		int posAfter = output.size();
 		output.putNumAsText(posConLen, posAfter - posBefore, false);

+ 1 - 1
frameworks/Java/servlet-dsl/benchmark_config.json

@@ -11,7 +11,7 @@
       "database": "None",
       "framework": "servlet-dsl",
       "language": "Java",
-      "orm": "None",
+      "orm": "raw",
       "platform": "Servlet",
       "webserver": "Resin",
       "os": "Linux",

+ 2 - 2
frameworks/JavaScript/express/package.json

@@ -7,9 +7,9 @@
     , "body-parser": "1.12.3"
     , "method-override": "2.3.2"
     , "errorhandler": "1.3.5"
-    , "mongoose": "4.0.1" 
+    , "mongoose": "4.0.1"
     , "async": "0.9.0"
-    , "jade": "0.29.0"
+    , "jade": "1.11.0"
     , "sequelize": "2.0.6"
     , "mysql": "2.6.2"
   }

+ 1 - 1
frameworks/JavaScript/express/views/fortunes/index.jade

@@ -5,7 +5,7 @@ block content
     tr
       th id
       th message
-    for fortune in fortunes
+    each fortune in fortunes
       tr
         td= fortune.id
         td= fortune.message

+ 1 - 1
frameworks/JavaScript/express/views/layout.jade

@@ -1,4 +1,4 @@
-!!! 5
+doctype
 html
   head
     title Fortunes

+ 13 - 232
frameworks/JavaScript/hapi/app.js

@@ -1,236 +1,17 @@
-/**
- * Module dependencies.
- */
-
-var cluster = require('cluster'),
-	numCPUs = require('os').cpus().length,
-	Hapi = require('hapi'),
-	Sequelize = require('sequelize'),
-	mongoose = require('mongoose'),
-	conn = mongoose.connect('mongodb://localhost/hello_world'),
-	async = require('async');
-
-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
-});
+var cluster = require('cluster');
+var numCPUs = require('os').cpus().length;
 
 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');
-	});
+  // Fork workers.
+  for (var i = 0; i < numCPUs; i++) {
+    cluster.fork();
+  }
+
+  console.log('Master starting ' + new Date().toISOString(" "));
+  cluster.on('exit', function (worker, code, signal) {
+    process.exit(1);
+  });
 } else {
-	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, 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, reply){
-			var queries = isNaN(req.params.queries) ? 1 : parseInt(req.params.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(callback);
-				});
-			}
-
-			async.parallel(queryFunctions, function(err, results){
-				if (!req.params.queries) {
-					results = results[0];
-				}
-				reply(results).header('Server', 'hapi');
-			});
-		}
-	});
-
-	server.route({
-		method: 'GET',
-		path: '/mysql-orm/{queries?}',
-		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);
-
-			for (var i = 1; i <= queries; i++) {
-				queryFunctions.push(function(callback){
-					World.findOne({
-						where: {
-							id: Math.floor(Math.random() * 10000) + 1}
-						}
-					).complete(callback);
-				});
-			}
-
-			async.parallel(queryFunctions, function(err, results){
-				if (!req.params.queries) {
-					results = results[0];
-				}
-				reply(results).header('Server', 'hapi');
-			});
-		}
-	});
-
-	server.route({
-		method: 'GET',
-		path: '/fortune',
-		handler: function(req,reply){
-			Fortune.findAll().complete(function(err, fortunes){
-				fortunes.push({
-					id: 0,
-					message: 'Additional fortune added at request time.'
-				});
-				fortunes.sort(function(a, b){
-					return (a.message < b.message) ? -1 : 1;
-				});
-
-				reply.view('fortunes', {
-					fortunes: fortunes
-				}).header('Server', 'hapi');
-			});
-		}
-	});
-
-	server.route({
-		method: 'GET',
-		path: '/mongoose-update/{queries?}',
-		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){
-					MWorld.findOne({ id: Math.floor(Math.random() * 10000) + 1 }).exec(callback);
-				});
-			}
-
-			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);
-				}
-
-				async.parallel(updateFunctions, function(err, updates) {
-					reply(worlds).header('Server', 'hapi');
-				});
-			});
-		}		
-	});
-
-	server.route({
-		method: 'GET',
-		path: '/mysql-orm-update/{queries?}',
-		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.findOne({
-						where: {
-							id: Math.floor(Math.random() * 10000) + 1}
-						}
-					).complete(callback);
-				});
-			}
-
-			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);
-							worlds[i].save().complete(callback);
-						});
-					})(i);
-				}
-
-				async.parallel(updateFunctions, function(err, updates) {
-					reply(worlds).header('Server', 'hapi');
-				});
-			});
-		}
-	});
-
-	server.start();
+  // worker task
+  require('./create-server');
 }

+ 52 - 9
frameworks/JavaScript/hapi/benchmark_config.json

@@ -22,16 +22,17 @@
     },
     "mongodb": {
       "setup_file": "setup",
-      "db_url": "/mongoose/",
-      "query_url": "/mongoose/",
-      "update_url": "/mongoose-update/",
+      "db_url": "/mongoose/db",
+      "query_url": "/mongoose/queries?queries=",
+      "fortune_url": "/mongoose/fortunes",
+      "update_url": "/mongoose/updates?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",
       "database": "MongoDB",
       "framework": "hapi",
       "language": "JavaScript",
-      "orm": "Raw",
+      "orm": "Full",
       "platform": "nodejs",
       "webserver": "None",
       "os": "Linux",
@@ -42,17 +43,59 @@
     },
     "mysql": {
       "setup_file": "setup",
-      "db_url": "/mysql-orm/",
-      "query_url": "/mysql-orm/",
-      "fortune_url": "/fortune",
-      "update_url": "/mysql-orm-update/",
+      "db_url": "/sequelize/db",
+      "query_url": "/sequelize/queries?queries=",
+      "fortune_url": "/sequelize/fortunes",
+      "update_url": "/sequelize/updates?queries=",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Micro",
       "database": "MySQL",
       "framework": "hapi",
       "language": "JavaScript",
-      "orm": "Raw",
+      "orm": "Full",
+      "platform": "nodejs",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "hapi",
+      "notes": "",
+      "versus": "node"
+    },
+    "postgres": {
+      "setup_file": "setup",
+      "db_url": "/sequelize-pg/db",
+      "query_url": "/sequelize-pg/queries?queries=",
+      "fortune_url": "/sequelize-pg/fortunes",
+      "update_url": "/sequelize-pg/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Postgres",
+      "framework": "hapi",
+      "language": "JavaScript",
+      "orm": "Full",
+      "platform": "nodejs",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "hapi",
+      "notes": "",
+      "versus": "node"
+    },
+    "redis": {
+      "setup_file": "setup",
+      "db_url": "/hiredis/db",
+      "query_url": "/hiredis/queries?queries=",
+      "fortune_url": "/hiredis/fortunes",
+      "update_url": "/hiredis/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Micro",
+      "database": "Redis",
+      "framework": "hapi",
+      "language": "JavaScript",
+      "orm": "Full",
       "platform": "nodejs",
       "webserver": "None",
       "os": "Linux",

+ 83 - 0
frameworks/JavaScript/hapi/create-server.js

@@ -0,0 +1,83 @@
+var Hapi = require('hapi');
+var server = new Hapi.Server();
+server.connection({port: 8080});
+server.views({
+  engines: {
+    hbs: require('handlebars')
+  },
+  path: __dirname + '/views',
+  compileOptions: {
+    pretty: false
+  }
+});
+
+var Promise = require('bluebird');
+var MongooseHandler;
+var SequelizeHandler;
+var SequelizePgHandler;
+var RedisHandler;
+
+// Slight start-up improvement loading handlers in parallel
+Promise.join(
+  require('./handlers/mongoose'),
+  require('./handlers/sequelize'),
+  require('./handlers/sequelize-postgres'),
+  require('./handlers/redis'),
+  function (mongo, mysql, pg, redis) {
+    MongooseHandler = mongo;
+    SequelizeHandler = mysql;
+    SequelizePgHandler = pg;
+    RedisHandler = redis;
+  })
+  .catch(function (err) {
+    console.log('There was a problem setting up the handlers');
+    process.exit(1);
+  });
+
+
+Route('/json', JsonSerialization);
+Route('/plaintext', Plaintext);
+
+Route('/mongoose/db', MongooseHandler.SingleQuery);
+Route('/mongoose/queries', MongooseHandler.MultipleQueries);
+Route('/mongoose/fortunes', MongooseHandler.Fortunes);
+Route('/mongoose/updates', MongooseHandler.Updates);
+
+Route('/sequelize/db', SequelizeHandler.SingleQuery);
+Route('/sequelize/queries', SequelizeHandler.MultipleQueries);
+Route('/sequelize/fortunes', SequelizeHandler.Fortunes);
+Route('/sequelize/updates', SequelizeHandler.Updates);
+
+Route('/sequelize-pg/db', SequelizePgHandler.SingleQuery);
+Route('/sequelize-pg/queries', SequelizePgHandler.MultipleQueries);
+Route('/sequelize-pg/fortunes', SequelizePgHandler.Fortunes);
+Route('/sequelize-pg/updates', SequelizePgHandler.Updates);
+
+Route('/hiredis/db', RedisHandler.SingleQuery);
+Route('/hiredis/queries', RedisHandler.MultipleQueries);
+Route('/hiredis/fortunes', RedisHandler.Fortunes);
+Route('/hiredis/updates', RedisHandler.Updates);
+
+
+function JsonSerialization(req, reply) {
+  reply({ message: 'Hello, World!' })
+    .header('Server', 'hapi');
+}
+
+function Plaintext(req, reply) {
+  reply('Hello, World!')
+    .header('Server', 'hapi')
+    .header('Content-Type', 'text/plain');
+}
+
+// Makes routing simpler as tfb routes are all GET's
+// We also don't use the nifty route features that Hapi has
+// to offer such as attaching a validator
+function Route(path, handler) {
+  server.route({ method: 'GET', path: path, handler: handler})
+}
+
+server.start(function (err) {
+  console.log('Hapi worker started and listening on ' + server.info.uri + " "
+    + new Date().toISOString(" "));
+});

+ 128 - 0
frameworks/JavaScript/hapi/handlers/mongoose.js

@@ -0,0 +1,128 @@
+// Connects to MongoDB using the mongoose driver
+// Handles related routes
+
+var h = require('../helper');
+var Promise = require('bluebird');
+// Can treat mongoose library as one that supports Promises
+// these methods will then have "-Async" appended to them.
+var Mongoose = Promise.promisifyAll(require('mongoose'));
+var connection = Mongoose.connect('mongodb://127.0.0.1/hello_world');
+
+var WorldSchema = new Mongoose.Schema({
+    id :          Number,
+    randomNumber: Number
+  }, {
+    collection: 'world'
+  });
+var FortuneSchema = new Mongoose.Schema({
+    id:      Number,
+    message: String
+  }, {
+    collection: 'fortune'
+  });
+
+var Worlds = connection.model('World', WorldSchema);
+var Fortunes = connection.model('Fortune', FortuneSchema);
+
+function randomWorldPromise() {
+  var id = h.randomTfbNumber();
+  var promise = Worlds
+    .findOneAsync({
+      id: id
+    })
+    .then(function (world) {
+      return world;
+    })
+    .catch(function (err) {
+      process.exit(1);
+    });
+  return promise;
+}
+
+function promiseAllFortunes() {
+  var promise = Fortunes
+    .findAsync({})
+    .then(function (fortunes) {
+      return fortunes;
+    })
+    .catch(function (err) {
+      process.exit(1);
+    });
+  return promise;
+}
+
+function updateWorld(world) {
+  var promise = Worlds
+    .updateAsync({
+      id: world.randomNumber
+    }, {
+      randomNumber: world.randomNumber
+    })
+    .then(function (result) {
+      return world;
+    })
+    .catch(function (err) {
+      process.exit(1);
+    });
+  return promise;
+}
+
+module.exports = {
+
+  SingleQuery: function(req, reply) {
+    randomWorldPromise()
+      .then(function (world) {
+        reply(world)
+          .header('Server', 'hapi');
+      });
+  },
+
+  MultipleQueries: function(req, reply) {
+    var queries = h.getQueries(req);
+    var worldPromises = h.fillArray(randomWorldPromise(), queries);
+
+    Promise
+      .all(worldPromises)
+      .then(function (worlds) {
+        reply(worlds)
+          .header('Server', 'hapi');
+      });
+  },
+
+  Fortunes: function(req, reply) {
+    promiseAllFortunes()
+      .then(function (fortunes) {
+        fortunes.push(h.ADDITIONAL_FORTUNE);
+        fortunes.sort(function (a, b) {
+          return a.message.localeCompare(b.message);
+        });
+      
+        reply.view('fortunes', {
+          fortunes: fortunes
+        })
+          .header('Content-Type', 'text/html')
+          .header('Server', 'hapi');
+      });
+  },
+
+  Updates: function(req, reply) {
+    var queries = h.getQueries(req);
+    var worldPromises = [];
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise());
+    }
+
+    Promise
+      .all(worldPromises)
+      .map(function (world) {
+        world.randomNumber = h.randomTfbNumber();
+        return updateWorld(world);
+      })
+      .then(function (worlds) {
+        reply(worlds)
+          .header('Server', 'hapi');
+      });
+  }
+
+};

+ 133 - 0
frameworks/JavaScript/hapi/handlers/redis.js

@@ -0,0 +1,133 @@
+// Connects to Redis using the node_redis and hiredis drivers
+// Handles related routes
+
+// "If hiredis [pure C library] is installed, node_redis will use it by default.
+// Otherwise, a pure JavaScript parser will be used."
+// >> hiredis is installed for these tests
+
+var h = require('../helper');
+var Promise = require('bluebird');
+// Can treat redis library as one that supports Promises
+// these methods will then have "-Async" appended to them.
+var redis = Promise.promisifyAll(require('redis'));
+var client = redis.createClient();
+
+client.on('error', function (err) {
+  console.log('Redis Error: ' + err);
+  // Do nothing further if Redis errors/is unavailable
+});
+
+function redisWorldId(id) {
+  return 'world:' + id;
+}
+
+function randomWorldPromise() {
+  var id = h.randomTfbNumber();
+  var redisId = redisWorldId(id);
+
+  var promise = client.getAsync(redisId)
+    .then(function (worldValue) {
+      return {
+        id: id,
+        randomNumber: worldValue
+      }
+    })
+    .catch(function (err) {
+      process.exit(1);
+    });
+  return promise;
+}
+
+function redisSetWorld(world) {
+  var redisId = redisWorldId(world.id);
+  var promise = client
+    .setAsync(redisId, world.randomNumber)
+    .then(function (result) {
+      return world;
+    })
+    .catch(function (err) {
+      process.exit(1);
+    });
+  return promise;
+}
+
+function redisGetAllFortunes() {
+  var promise = client
+    .lrangeAsync('fortunes', 0, -1)
+    .then(function (fortuneMessages) {
+      var fortunes = fortuneMessages.map(function (e, i) {
+        return { id: i + 1, message: e }
+      });
+      return fortunes;
+    })
+    .catch(function (err) {
+      if (err) { return process.exit(1); }
+    });
+  return promise;
+}
+
+
+module.exports = {
+  
+  SingleQuery: function(req, reply) {
+    randomWorldPromise()
+      .then(function (world) {
+        reply(world)
+          .header('Server', 'hapi');
+      })
+      .catch(function (err) {
+        if (err) { return process.exit(1); }
+      })
+  },
+
+  MultipleQueries: function(req, reply) {
+    var queries = h.getQueries(req);
+    var worldPromises = h.fillArray(randomWorldPromise(), queries);
+
+    Promise
+      .all(worldPromises)
+      .then(function (worlds) {
+         reply(worlds)
+          .header('Server', 'hapi');
+      });
+  },
+
+  Fortunes: function(req, reply) {
+    redisGetAllFortunes()
+      .then(function (fortunes) {
+        fortunes.push(h.ADDITIONAL_FORTUNE);
+        fortunes.sort(function (a, b) {
+          return a.message.localeCompare(b.message);
+        });
+
+        reply.view('fortunes', {
+          fortunes: fortunes
+        })
+          .header('Content-Type', 'text/html')
+          .header('Server', 'hapi');
+      })
+      .catch(function (err) {
+        process.exit(1);
+      })
+  },
+
+  Updates: function(req, reply) {
+    var queries = h.getQueries(req)
+    var worldPromises = h.fillArray(randomWorldPromise(), queries);
+
+    Promise
+      .all(worldPromises)
+      .map(function (world) {
+        world.randomNumber = h.randomTfbNumber();
+        return redisSetWorld(world);
+      })
+      .then(function (updated) {
+        reply(updated)
+          .header('Server', 'hapi');
+      })
+      .catch(function (err) {
+        process.exit(1);
+      });
+  }
+
+};

+ 117 - 0
frameworks/JavaScript/hapi/handlers/sequelize-postgres.js

@@ -0,0 +1,117 @@
+// Connects to Postgres using the sequelize driver
+// Handles related routes
+
+var h = require('../helper');
+var Promise = require('bluebird');
+var Sequelize = require('sequelize');
+
+var sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', {
+  host: '127.0.0.1',
+  dialect: 'postgres',
+  logging: false
+});
+
+var Worlds = sequelize.define('World', {
+  id:           { type: 'Sequelize.INTEGER' },
+  randomnumber: { type: 'Sequelize.INTEGER' }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
+
+var Fortunes = sequelize.define('Fortune', {
+  id:           { type: 'Sequelize.INTEGER' },
+  message:      { type: 'Sequelize.STRING' }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
+
+var randomWorldPromise = function() {
+  return Worlds.findOne({
+    where: { id: h.randomTfbNumber() }
+  }).then(function (results) {
+    return results;
+  }).catch(function (err) {
+    process.exit(1);
+  });
+}
+
+module.exports = {
+
+  SingleQuery: function (req, reply) {
+    randomWorldPromise().then(function (world) {
+      reply(world)
+        .header('Server', 'hapi');
+    })
+  },
+
+  MultipleQueries: function (req, reply) {
+    var queries = h.getQueries(req);
+    var worldPromises = [];
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise());
+    }
+
+    Promise.all(worldPromises).then(function (worlds) {
+      reply(worlds)
+        .header('Server', 'hapi');
+    });
+  },
+
+  Fortunes: function (req, reply) {
+    Fortunes.findAll().then(function (fortunes) {
+      fortunes.push(h.ADDITIONAL_FORTUNE);
+      fortunes.sort(function (a, b) {
+        return a.message.localeCompare(b.message);
+      });
+
+      reply.view('fortunes', {
+        fortunes: fortunes
+      })
+        .header('Content-Type', 'text/html')
+        .header('Server', 'hapi');
+    }).catch(function (err) {
+      process.exit(1);
+    }); 
+  },
+
+  Updates: function (req, reply) {
+    var queries = h.getQueries(req);
+    var worldPromises = [];
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise());
+    }
+
+    var worldUpdate = function (world) {
+      world.randomNumber = h.randomTfbNumber();
+
+      return Worlds.update(
+          { randomNumber: world.randomNumber },
+          { where: { id: world.id } }
+        )
+        .then(function (results) {
+          return world;
+        })
+        .catch(function (err) {
+          process.exit(1);
+        });
+    }
+
+    Promise
+      .all(worldPromises)
+      .map(function (world) {
+        return worldUpdate(world);
+      })
+      .then(function (updated) {
+        reply(updated)
+          .header('Server', 'hapi')
+      })
+      .catch(function (err) {
+        process.exit(1);
+      });
+  }
+
+};

+ 116 - 0
frameworks/JavaScript/hapi/handlers/sequelize.js

@@ -0,0 +1,116 @@
+// Connects to MySQL using the sequelize driver
+// Handles related routes
+
+var h = require('../helper');
+var Promise = require('bluebird');
+
+var Sequelize = require('sequelize');
+var sequelize = new Sequelize('hello_world', 'benchmarkdbuser', 'benchmarkdbpass', {
+  host: '127.0.0.1',
+  dialect: 'mysql',
+  logging: false
+});
+
+var Worlds = sequelize.define('World', {
+  id:           { type: 'Sequelize.INTEGER' },
+  randomNumber: { type: 'Sequelize.INTEGER' }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
+
+var Fortunes = sequelize.define('Fortune', {
+  id:           { type: 'Sequelize.INTEGER' },
+  message:      { type: 'Sequelize.STRING' }
+}, {
+  timestamps: false,
+  freezeTableName: true
+});
+
+var randomWorldPromise = function() {
+  return Worlds.findOne({
+    where: { id: h.randomTfbNumber() }
+  }).then(function (results) {
+    return results;
+  }).catch(function (err) {
+    process.exit(1);
+  });
+}
+
+module.exports = {
+
+  SingleQuery: function (req, reply) {
+    randomWorldPromise().then(function (world) {
+      reply(world)
+        .header('Server', 'hapi');
+    })
+  },
+
+  MultipleQueries: function (req, reply) {
+    var queries = h.getQueries(req);
+    var worldPromises = [];
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise());
+    }
+
+    Promise.all(worldPromises).then(function (worlds) {
+      reply(worlds)
+        .header('Server', 'hapi');
+    });
+  },
+
+  Fortunes: function (req, reply) {
+    Fortunes.findAll().then(function (fortunes) {
+      fortunes.push(h.ADDITIONAL_FORTUNE);
+      fortunes.sort(function (a, b) {
+        return a.message.localeCompare(b.message);
+      });
+
+      reply.view('fortunes', {
+        fortunes: fortunes
+      })
+        .header('Content-Type', 'text/html')
+        .header('Server', 'hapi');
+    }).catch(function (err) {
+      process.exit(1);
+    }); 
+  },
+
+  Updates: function (req, reply) {
+    var queries = h.getQueries(req);
+    var worldPromises = [];
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise());
+    }
+
+    var worldUpdate = function (world) {
+      world.randomNumber = h.randomTfbNumber();
+
+      return Worlds.update(
+          { randomNumber: world.randomNumber },
+          { where: { id: world.id } }
+        )
+        .then(function (results) {
+          return world;
+        })
+        .catch(function (err) {
+          process.exit(1);
+        });
+    }
+
+    Promise
+      .all(worldPromises)
+      .map(function (world) {
+        return worldUpdate(world);
+      })
+      .then(function (updated) {
+        reply(updated)
+          .header('Server', 'hapi')
+      })
+      .catch(function (e) {
+        process.exit(1);
+      });
+  }
+}

+ 31 - 0
frameworks/JavaScript/hapi/helper.js

@@ -0,0 +1,31 @@
+var Handlebars = require('handlebars');
+
+var GREETING = "Hello, World";
+var HELLO_OBJ = { message: GREETING }
+
+module.exports = {
+  randomTfbNumber: function() {
+    return Math.floor(Math.random() * 10000) + 1;
+  },
+
+  fillArray: function(value, len) {
+    var filled = [];
+
+    for (var i = 0; i < len; i++) {
+      filled.push(value);
+    }
+    return filled;
+  },
+
+  getQueries: function(req) {
+    var queries = ~~(req.query.queries) || 1;
+    queries = Math.min(Math.max(queries, 1), 500);
+    return queries;
+  },
+
+  ADDITIONAL_FORTUNE: {
+    id: 0,
+    message: 'Additional fortune added at request time.'
+  }
+
+}

+ 16 - 11
frameworks/JavaScript/hapi/package.json

@@ -1,13 +1,18 @@
 {
-	"name": "application-name",
-	"version": "0.0.1",
-	"private": true,
-	"dependencies": {
-		"hapi": "8.4.0",
-		"mongoose": "4.0.1",
-		"async": "0.9.0",
-		"handlebars": "3.0.1",
-		"sequelize": "2.0.6",
-		"mysql": "2.6.2"
-	}
+  "name": "application-name",
+  "version": "0.0.1",
+  "private": true,
+  "dependencies": {
+    "async": "1.2.0",
+    "bluebird": "^2.9.27",
+    "handlebars": "3.0.3",
+    "hapi": "8.6.0",
+    "hiredis": "^0.4.0",
+    "mongoose": "4.0.4",
+    "mysql": "2.7.0",
+    "pg": "^4.3.0",
+    "pg-hstore": "^2.3.2",
+    "redis": "^0.12.1",
+    "sequelize": "3.1.1"
+  }
 }

+ 3 - 1
frameworks/JavaScript/hapi/setup.sh

@@ -14,4 +14,6 @@ npm install -g npm
 
 # run app
 npm install
-node app &
+node app &
+echo "sleeping additional 30 seconds for hapi..."
+sleep 30

+ 1 - 0
frameworks/JavaScript/hapi/views/fortunes.hbs

@@ -0,0 +1 @@
+<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>{{#fortunes}}<tr><td>{{id}}</td><td>{{message}}</td></tr>{{/fortunes}}</table></body></html>

+ 0 - 21
frameworks/JavaScript/hapi/views/fortunes.html

@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-	<title>Fortunes</title>
-</head>
-
-<body>
-	<table>
-		<tr>
-			<th>id</th>
-			<th>message</th>
-		</tr>
-{{#fortunes}}
-		<tr>
-			<td>{{id}}</td>
-			<td>{{message}}</td>
-		</tr>
-{{/fortunes}}
-	</table>
-</body>
-</html>

+ 0 - 167
frameworks/JavaScript/sailsjs/api/controllers/DatabaseQueryController.js

@@ -1,167 +0,0 @@
-/**
- * DatabaseQueryController
- *
- * @description :: Server-side logic for managing Database Queries
- */
-
-var Sequelize = require('sequelize')
-var sequelize = new Sequelize(
-  'hello_world', 'benchmarkdbuser', 'benchmarkdbpass',
-  {
-    host: '127.0.0.1',
-    dialect: 'mysql',
-    pool: {
-      max: 5000,
-      min: 0,
-      idle: 5000
-    },
-    // hide the SQL queries being run
-    logging: false
-  });
-
-
-var World = sequelize.define('World', {
-  id: Sequelize.INTEGER,
-  randomNumber: Sequelize.INTEGER
-},
-{
-  // prevents sequelize from assuming the table is called 'Worlds'
-  freezeTableName: true,
-  timestamps: false
-});
-
-
-var Fortune = sequelize.define('Fortune', {
-  id: Sequelize.INTEGER,
-  message: Sequelize.STRING
-},
-{
-  // prevents sequelize from assuming the table is called 'Fortunes'
-  freezeTableName: true,
-  timestamps: false
-});
-
-
-var randomTFBnumber = function() {
-  return Math.floor(Math.random() * 10000) + 1;
-}
-
-
-var worldQuery = function(callback) {
-  World.findOne({
-    where: { id: randomTFBnumber()}
-  }).then(function (result) {
-    if (result) {
-      callback(null, result.get())
-    } else {
-      callback("Error in World query")
-    }
-  });
-}
-
-// arr is single-element array containing number of updated rows
-// [ 1 ] or [ 0 ]
-var oneOrMoreUpdates = function (arr) {
-  return arr[0] > 0;
-}
-
-
-var worldUpdate = function(world, callback) {
-  World.update({
-    randomNumber: world.randomNumber
-  },
-  {
-    where: {
-      id: world.id
-    }
-  }).then(function (changed) {
-    if (oneOrMoreUpdates(changed)) {
-      callback(null, world);
-    } else {
-      callback("Error in World update");
-    }
-  });
-}
-
-
-module.exports = {
-
-  /**
-   * Test 2: Single Database Query
-   */
-  single: function(req, res) {
-    World.findOne({
-      where: { id: randomTFBnumber() }
-    }).then(function (results) {
-      return res.json(results.get());
-    })
-  },
-
-
-  /**
-   * Test 3: Multiple Database Query
-   */
-  multiple: function(req, res) {
-    var queries = req.param('queries');
-    var toRun = [];
-
-    queries = Math.min(Math.max(queries, 1), 500) || 1;
-
-    for (var i = 0; i < queries; i++) {
-      toRun.push(worldQuery);
-    }
-
-    async.parallel(toRun, function (err, results) {
-      if (!err) {
-        res.json(results);
-      } else {
-        res.badRequest('Unexpected failure to fetch multiple records.');
-      }
-    });
-  },
-
-
-  /**
-   * Test 4: Fortunes
-   */
-  fortunes: function(req, res) {
-    Fortune.findAll().then(function (fortunes) {
-      fortunes.push({
-        id: 0,
-        message: "Additional fortune added at request time."
-      });
-      fortunes.sort(function (a, b) {
-        return a.message.localeCompare(b.message);
-      });
-      return res.render('fortunes', { 'fortunes': fortunes });
-    })
-  },
-
-
-  /**
-   * Test 5: Database Updates
-   */
-  updates: function(req, res) {
-    var queries = req.param('queries');
-    var worlds = [];
-
-    queries = Math.min(Math.max(queries, 1), 500) || 1;
-
-    for (var i = 0; i < queries; i++) {
-      worlds.push({
-        id: randomTFBnumber(),
-        randomNumber: randomTFBnumber()
-      });
-    }
-
-    async.map(worlds, worldUpdate, function (err, results) {
-      if (!err) {
-        res.json(results);
-      } else {
-        res.badRequest('Unexpected failure to update records.');
-      }
-    });
-  }
-  
-};
-

+ 136 - 0
frameworks/JavaScript/sailsjs/api/controllers/RedisController.js

@@ -0,0 +1,136 @@
+/**
+ * RedisController
+ *
+ * @description :: Connects to Redis using the node_redis and hiredis drivers
+ *   Handles redis routes
+ *   "If hiredis [pure C library] is installed, node_redis will use it by default.
+ *   Otherwise, a pure JavaScript parser will be used."
+ *   >> hiredis is installed for these tests
+ */
+
+var h = require('../services/helper')
+var Promise = require('bluebird')
+// Can treat redis library as one that supports Promises
+// these methods will then have "-Async" appended to them.
+var redis = Promise.promisifyAll(require('redis'))
+var client = redis.createClient()
+
+client.on('error', function (err) {
+  console.log('Redis Error: ' + err)
+  // Do nothing further if Redis errors/is unavailable
+});
+
+function redisWorldId(id) {
+  return 'world:' + id
+}
+
+function randomWorldPromise() {
+  var id = h.randomTfbNumber()
+  var redisId = redisWorldId(id)
+
+  var promise = client.getAsync(redisId)
+    .then(function (worldValue) {
+      return {
+        id: id,
+        randomNumber: worldValue
+      }
+    })
+    .catch(function (err) {
+      console.log(err.stack)
+    })
+  return promise
+}
+
+function redisSetWorld(world) {
+  var redisId = redisWorldId(world.id)
+  var promise = client
+    .setAsync(redisId, world.randomNumber)
+    .then(function (result) {
+      return world
+    })
+    .catch(function (err) {
+      console.log(err.stack)
+    })
+  return promise
+}
+
+function redisGetAllFortunes() {
+  var promise = client
+    .lrangeAsync('fortunes', 0, -1)
+    .then(function (fortuneMessages) {
+      var fortunes = fortuneMessages.map(function (e, i) {
+        return { id: i + 1, message: e }
+      })
+      return fortunes;
+    })
+    .catch(function (err) {
+      console.log(err.stack)
+    })
+  return promise
+}
+
+
+module.exports = {
+  
+  Single: function(req, res) {
+    randomWorldPromise()
+      .then(function (world) {
+        res.json(world)
+      })
+      .catch(function (err) {
+        console.log(err.stack)
+      })
+  },
+
+  Multiple: function(req, res) {
+    var queries = h.getQueries(req)
+    var worldPromises = []
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise())
+    }
+
+    Promise
+      .all(worldPromises)
+      .then(function (worlds) {
+         res.json(worlds)
+      });
+  },
+
+  Fortunes: function(req, res) {
+    redisGetAllFortunes()
+      .then(function (fortunes) {
+        fortunes.push(h.ADDITIONAL_FORTUNE)
+        fortunes.sort(function (a, b) {
+          return a.message.localeCompare(b.message)
+        })
+        res.render('fortunes', { fortunes: fortunes })
+      })
+      .catch(function (err) {
+        console.log(err.stack)
+      })
+  },
+
+  Updates: function(req, res) {
+    var queries = h.getQueries(req)
+    var worldPromises = []
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise())
+    }
+
+    Promise
+      .all(worldPromises)
+      .map(function (world) {
+        world.randomNumber = h.randomTfbNumber()
+        return redisSetWorld(world)
+      })
+      .then(function (updated) {
+        res.json(updated)
+      })
+      .catch(function (err) {
+        console.log(err.stack)
+      })
+  }
+
+};

+ 154 - 0
frameworks/JavaScript/sailsjs/api/controllers/SequelizeMySQLController.js

@@ -0,0 +1,154 @@
+/**
+ * SequelizeMySQLController
+ *
+ * @description :: Server-side logic for managing Database Queries
+ */
+
+var h = require('../services/helper')
+var Promise = require('bluebird')
+
+var Sequelize = require('sequelize')
+var sequelize = new Sequelize(
+  'hello_world', 'benchmarkdbuser', 'benchmarkdbpass',
+  {
+    host: '127.0.0.1',
+    dialect: 'mysql',
+    pool: {
+      max: 5000,
+      min: 0,
+      idle: 5000
+    },
+    // hide the SQL queries being run
+    logging: false
+  })
+
+
+var Worlds = sequelize.define('World', {
+  id: Sequelize.INTEGER,
+  randomNumber: Sequelize.INTEGER
+},
+{
+  // prevents sequelize from assuming the table is called 'Worlds'
+  freezeTableName: true,
+  timestamps: false
+})
+
+
+var Fortunes = sequelize.define('Fortune', {
+  id: Sequelize.INTEGER,
+  message: Sequelize.STRING
+},
+{
+  // prevents sequelize from assuming the table is called 'Fortunes'
+  freezeTableName: true,
+  timestamps: false
+})
+
+
+var randomWorldPromise = function() {
+  var promise = Worlds
+    .findOne({
+      where: { id: h.randomTfbNumber() }
+    })
+    .then(function (world) {
+      return world
+    })
+    .catch(function (err) {
+      process.exit(1)
+    })
+  return promise
+}
+
+var updateWorld = function(world) {
+  var promise = Worlds
+    .update(
+      { randomNumber: world.randomNumber },
+      { where: { id: world.id } }
+    )
+    .then(function (results) {
+      return world
+    })
+    .catch(function (err) {
+      process.exit(1)
+    })
+  return promise
+}
+
+
+module.exports = {
+
+  /**
+   * Test 2: Single Database Query
+   */
+  Single: function(req, res) {
+    randomWorldPromise()
+      .then(function (world) {
+        res.json(world)
+      })
+  },
+
+
+  /**
+   * Test 3: Multiple Database Query
+   */
+  Multiple: function(req, res) {
+    var queries = h.getQueries(req)
+    var toRun = []
+
+    for (var i = 0; i < queries; i++) {
+      toRun.push(randomWorldPromise());
+    }
+
+    Promise
+      .all(toRun)
+      .then(function (worlds) {
+        res.json(worlds)
+      })
+  },
+
+
+  /**
+   * Test 4: Fortunes
+   */
+  Fortunes: function(req, res) {
+    Fortunes
+      .findAll()
+      .then(function (fortunes) {
+        fortunes.push(h.ADDITIONAL_FORTUNE)
+        fortunes.sort(function (a, b) {
+          return a.message.localeCompare(b.message)
+        })
+        res.render('fortunes', { 'fortunes': fortunes })
+      })
+      .catch(function (err) {
+        process.exit(1)
+      })
+  },
+
+
+  /**
+   * Test 5: Database Updates
+   */
+  Updates: function(req, res) {
+    var queries = h.getQueries(req);
+    var worldPromises = [];
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise())
+    }
+
+    Promise
+      .all(worldPromises)
+      .map(function (world) {
+        return updateWorld(world)
+      })
+      .then(function (updated) {
+        res.json(updated)
+      })
+      .catch(function (err) {
+        process.exit(1)
+      })
+  }
+  
+};
+

+ 155 - 0
frameworks/JavaScript/sailsjs/api/controllers/SequelizePostgresController.js

@@ -0,0 +1,155 @@
+/**
+ * SequelizePostgresController
+ *
+ * @description :: Server-side logic for managing Database Queries
+ */
+
+var h = require('../services/helper')
+var Promise = require('bluebird')
+
+var Sequelize = require('sequelize')
+var sequelize = new Sequelize(
+  'hello_world', 'benchmarkdbuser', 'benchmarkdbpass',
+  {
+    host: '127.0.0.1',
+    dialect: 'postgres',
+    pool: {
+      max: 5000,
+      min: 0,
+      idle: 5000
+    },
+    // hide the SQL queries being run
+    logging: false
+  })
+
+
+var Worlds = sequelize.define('World', {
+  id: Sequelize.INTEGER,
+  randomnumber: Sequelize.INTEGER
+},
+{
+  // prevents sequelize from assuming the table is called 'Worlds'
+  freezeTableName: true,
+  timestamps: false
+})
+
+
+var Fortunes = sequelize.define('Fortune', {
+  id: Sequelize.INTEGER,
+  message: Sequelize.STRING
+},
+{
+  // prevents sequelize from assuming the table is called 'Fortunes'
+  freezeTableName: true,
+  timestamps: false
+})
+
+
+var randomWorldPromise = function() {
+  var promise = Worlds
+    .findOne({
+      where: { id: h.randomTfbNumber() }
+    })
+    .then(function (world) {
+      return world
+    })
+    .catch(function (err) {
+      process.exit(1)
+    })
+  return promise
+}
+
+var updateWorld = function(world) {
+  var promise = Worlds
+    .update(
+      { randomNumber: world.randomNumber },
+      { where: { id: world.id } }
+    )
+    .then(function (results) {
+      return world
+    })
+    .catch(function (err) {
+      process.exit(1)
+    })
+  return promise
+}
+
+
+module.exports = {
+
+
+  /**
+   * Test 2: Single Database Query
+   */
+  Single: function(req, res) {
+    randomWorldPromise()
+      .then(function (world) {
+        res.json(world)
+      })
+  },
+
+
+  /**
+   * Test 3: Multiple Database Query
+   */
+  Multiple: function(req, res) {
+    var queries = h.getQueries(req)
+    var toRun = []
+
+    for (var i = 0; i < queries; i++) {
+      toRun.push(randomWorldPromise())
+    }
+
+    Promise
+      .all(toRun)
+      .then(function (worlds) {
+        res.json(worlds)
+      })
+  },
+
+
+  /**
+   * Test 4: Fortunes
+   */
+  Fortunes: function(req, res) {
+    Fortunes
+      .findAll()
+      .then(function (fortunes) {
+        fortunes.push(h.ADDITIONAL_FORTUNE)
+        fortunes.sort(function (a, b) {
+          return a.message.localeCompare(b.message)
+        })
+        res.render('fortunes', { 'fortunes': fortunes })
+      })
+      .catch(function (err) {
+        process.exit(1)
+      })
+  },
+
+
+  /**
+   * Test 5: Database Updates
+   */
+  Updates: function(req, res) {
+    var queries = h.getQueries(req)
+    var worldPromises = []
+
+    for (var i = 0; i < queries; i++) {
+      worldPromises.push(randomWorldPromise())
+    }
+
+    Promise
+      .all(worldPromises)
+      .map(function (world) {
+        return updateWorld(world)
+      })
+      .then(function (updated) {
+        res.json(updated)
+      })
+      .catch(function (err) {
+        process.exit(1)
+      })
+  }
+
+}
+

+ 2 - 2
frameworks/JavaScript/sailsjs/api/controllers/StaticTestController.js

@@ -12,7 +12,7 @@ module.exports = {
   /**
    * Test 1: JSON Serialization
    */
-  json: function (req, res) {
+  Json: function (req, res) {
     return res.json({
       message: 'Hello, World!'
     });
@@ -21,7 +21,7 @@ module.exports = {
   /**
    * Test 6: Plaintext
    */
-  plaintext: function (req, res) {
+  Plaintext: function (req, res) {
   	res.setHeader('Content-Type', 'text/plain');
   	return res.send("Hello, World!");
   }

+ 20 - 0
frameworks/JavaScript/sailsjs/api/services/helper.js

@@ -0,0 +1,20 @@
+
+
+module.exports = {
+
+  randomTfbNumber: function() {
+    return Math.floor(Math.random() * 10000) + 1
+  },
+
+  getQueries: function(req) {
+    var queries = req.param('queries')
+    queries = ~~(queries) || 1
+    return Math.min(Math.max(queries, 1), 500)
+  },
+
+  ADDITIONAL_FORTUNE: {
+    id: 0,
+    message: "Additional fortune added at request time."
+  }
+
+}

+ 48 - 6
frameworks/JavaScript/sailsjs/benchmark_config.json

@@ -4,18 +4,60 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=",
+      "db_url": "/mysql/db",
+      "query_url": "/mysql/queries?queries=",
+      "fortune_url": "/mysql/fortunes",
+      "update_url": "/mysql/updates?queries=",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Fullstack",
-      "database": "MySQL",
+      "database": "None",
       "framework": "sailsjs",
       "language": "JavaScript",
-      "orm": "Waterline",
+      "orm": "Micro",
+      "platform": "nodejs",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sails.js",
+      "notes": "",
+      "versus": "node"
+    },
+    "postgres": {
+      "setup_file": "setup",
+      "db_url": "/postgres/db",
+      "query_url": "/postgres/queries?queries=",
+      "fortune_url": "/postgres/fortunes",
+      "update_url": "/postgres/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "sailsjs",
+      "language": "JavaScript",
+      "orm": "Full",
+      "platform": "nodejs",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Sails.js",
+      "notes": "",
+      "versus": "node"
+    },
+    "redis": {
+      "setup_file": "setup",
+      "db_url": "/hiredis/db",
+      "query_url": "/hiredis/queries?queries=",
+      "fortune_url": "/hiredis/fortunes",
+      "update_url": "/hiredis/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Redis",
+      "framework": "sailsjs",
+      "language": "JavaScript",
+      "orm": "Full",
       "platform": "nodejs",
       "webserver": "None",
       "os": "Linux",

+ 20 - 7
frameworks/JavaScript/sailsjs/config/routes.js

@@ -36,13 +36,6 @@ module.exports.routes = {
     view: 'homepage'
   },
 
-  'get /json':      'StaticTestController.json',
-  'get /db':        'DatabaseQueryController.single',
-  'get /queries':   'DatabaseQueryController.multiple',
-  'get /fortunes':  'DatabaseQueryController.fortunes',
-  'get /updates':   'DatabaseQueryController.updates',
-  'get /plaintext': 'StaticTestController.plaintext'
-
   /***************************************************************************
   *                                                                          *
   * Custom routes here...                                                    *
@@ -53,4 +46,24 @@ module.exports.routes = {
   *                                                                          *
   ***************************************************************************/
 
+  // TFB routes here
+
+  'get /json':              'StaticTestController.Json',
+  'get /plaintext':         'StaticTestController.Plaintext',
+
+  'get /mysql/db':          'SequelizeMySQLController.Single',
+  'get /mysql/queries':     'SequelizeMySQLController.Multiple',
+  'get /mysql/fortunes':    'SequelizeMySQLController.Fortunes',
+  'get /mysql/updates':     'SequelizeMySQLController.Updates',
+
+  'get /postgres/db':       'SequelizePostgresController.Single',
+  'get /postgres/queries':  'SequelizePostgresController.Multiple',
+  'get /postgres/fortunes': 'SequelizePostgresController.Fortunes',
+  'get /postgres/updates':  'SequelizePostgresController.Updates',
+
+  'get /hiredis/db':        'RedisController.Single',
+  'get /hiredis/queries':   'RedisController.Multiple',
+  'get /hiredis/fortunes':  'RedisController.Fortunes',
+  'get /hiredis/updates':   'RedisController.Updates'
+
 };

+ 26 - 21
frameworks/JavaScript/sailsjs/package.json

@@ -2,30 +2,35 @@
   "name": "sailsjs",
   "private": true,
   "version": "0.0.0",
-  "description": "a Sails application",
+  "description": "a Sails application for TFB testing",
   "keywords": [],
   "dependencies": {
-    "async": "^0.9.0",
-    "ejs": "~0.8.4",
-    "grunt": "0.4.2",
-    "grunt-contrib-clean": "~0.5.0",
-    "grunt-contrib-coffee": "~0.10.1",
-    "grunt-contrib-concat": "~0.3.0",
-    "grunt-contrib-copy": "~0.5.0",
-    "grunt-contrib-cssmin": "~0.9.0",
+    "async": "^1.2.0",
+    "bluebird": "^2.9.27",
+    "ejs": "~2.3.1",
+    "grunt": "0.4.5",
+    "grunt-contrib-clean": "~0.6.0",
+    "grunt-contrib-coffee": "~0.13.0",
+    "grunt-contrib-concat": "~0.5.1",
+    "grunt-contrib-copy": "~0.8.0",
+    "grunt-contrib-cssmin": "~0.12.3",
     "grunt-contrib-jst": "~0.6.0",
-    "grunt-contrib-less": "0.11.1",
-    "grunt-contrib-uglify": "~0.4.0",
-    "grunt-contrib-watch": "~0.5.3",
-    "grunt-sails-linker": "~0.9.5",
-    "grunt-sync": "~0.0.4",
+    "grunt-contrib-less": "1.0.1",
+    "grunt-contrib-uglify": "~0.9.1",
+    "grunt-contrib-watch": "~0.6.1",
+    "grunt-sails-linker": "~0.10.1",
+    "grunt-sync": "~0.2.3",
     "handlebars": "^3.0.3",
-    "include-all": "~0.1.3",
-    "mysql": "^2.6.2",
-    "rc": "~0.5.0",
+    "hiredis": "^0.4.0",
+    "include-all": "~0.1.6",
+    "mysql": "^2.7.0",
+    "pg": "^4.4.0",
+    "pg-hstore": "^2.3.2",
+    "rc": "~1.0.3",
+    "redis": "^0.12.1",
     "sails": "~0.11.0",
-    "sails-disk": "~0.10.0",
-    "sequelize": "^3.0.0"
+    "sails-disk": "~0.10.8",
+    "sequelize": "^3.2.0"
   },
   "scripts": {
     "start": "node app.js",
@@ -34,8 +39,8 @@
   "main": "app.js",
   "repository": {
     "type": "git",
-    "url": "git://github.com/zane/sailsjs.git"
+    "url": "https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/JavaScript/sailsjs"
   },
-  "author": "zane",
+  "author": "zane-techempower",
   "license": ""
 }

+ 2 - 2
frameworks/Lua/lapis/setup.sh

@@ -4,7 +4,7 @@ sed -i 's|DBHOSTNAME|'"${DBHOST}"'|g' config.lua
 sed -i 's|DBHOSTNAME|'"${DBHOST}"'|g' config.moon
 sed -i 's|DBHOSTNAME|'"${DBHOST}"'|g' nginx.conf
 
-export LAPIS_OPENRESTY=${IROOT}/openresty-1.7.7.1
+export LAPIS_OPENRESTY=${IROOT}/openresty-1.7.10.1
 export PATH=${LAPIS_OPENRESTY}/nginx/sbin:$PATH
 
-lapis server production &
+lapis server production &

+ 2 - 2
frameworks/Lua/openresty/setup.sh

@@ -1,7 +1,7 @@
 #!/bin/bash
-export OPENRESTY_HOME=${IROOT}/openresty-1.7.7.1
+export OPENRESTY_HOME=${IROOT}/openresty-1.7.10.1
 
 sed -i 's|CWD|'"${TROOT}"'|g' nginx.conf
 sed -i 's|DBHOSTNAME|'"${DBHOST}"'|g' app.lua
 
-${OPENRESTY_HOME}/nginx/sbin/nginx -c $TROOT/nginx.conf -g "worker_processes '"${MAX_THREADS}"';" &
+${OPENRESTY_HOME}/nginx/sbin/nginx -c $TROOT/nginx.conf -g "worker_processes '"${MAX_THREADS}"';" &

+ 3 - 0
frameworks/PHP/clancats/.bowerrc

@@ -0,0 +1,3 @@
+{
+  "directory": "public/assets/vendor"
+}

+ 12 - 0
frameworks/PHP/clancats/.gitignore

@@ -0,0 +1,12 @@
+public/assets/packtacular/
+CCF/app/config/migrator.json
+CCF/vendor/
+storage/
+.DS_Store
+Thumbs.db
+composer.phar
+composer.lock
+phpunit.xml
+phpunit.phar
+report/
+run

+ 72 - 0
frameworks/PHP/clancats/app/App.php

@@ -0,0 +1,72 @@
+<?php 
+/*
+ *---------------------------------------------------------------
+ * Application Object
+ *---------------------------------------------------------------
+ *
+ * This is your default application object.
+ */
+class App extends CCApp 
+{	
+	/**
+	 * The application name
+	 *
+	 * @var string
+	 */
+	public static $name = 'My Application';
+	
+	/**
+	 * App configuration
+	 *
+	 * @var CCConfig
+	 */
+	public static $config = null;
+	
+	/**
+	 * current user object
+	 *
+	 * @var User
+	 */
+	public static $user = null;
+	
+	/**
+	 * Application initialization.
+	 * do your inital stuff here like getting the current user object ect..
+	 * You can return a CCResponse wich will cancle all other actions 
+	 * if enebaled ( see. main.config -> send_app_wake_response )
+	 *
+	 * @return void | CCResponse
+	 */
+	public static function wake() 
+	{
+		/*
+		 * Start the session by adding the current uri
+		 */
+		//CCSession::set( 'uri', CCServer::uri() );
+		
+		/*
+		 * try to authenticate the user
+		 */
+		//static::$user =& CCAuth::handler()->user;
+		
+		/*
+		 * load the App configuration
+		 */
+		//static::$config = CCConfig::create( 'app' );
+	}
+	
+	/**
+	 * Environment wake
+	 * This is an environment wake they get called if your running
+	 * the application in a special environment like:
+	 *     wake_production
+	 *     wake_phpunit
+	 *     wake_test
+	 *
+	 * @return void | CCResponse
+	 */
+	public static function wake_development() 
+	{	
+		CCProfiler::check( 'App::development - Application finished wake events.' );
+	}
+}

+ 24 - 0
frameworks/PHP/clancats/app/config/database.config.php

@@ -0,0 +1,24 @@
+<?php 
+/*
+ *---------------------------------------------------------------
+ * Database configuration
+ *---------------------------------------------------------------
+ */
+return array(
+	/*
+	 * the default database
+	 */
+	'main' =>  array(
+		// selected database
+		'db'	 => 'hello_world',
+	
+		// driver
+		'driver' => 'mysql',
+	
+		// auth
+		'host'		=> 'localhost',
+		'user' 		=> 'benchmarkdbuser',
+		'pass'		=> 'benchmarkdbpass',
+		'charset'	=> 'utf8'
+	),
+);

+ 27 - 0
frameworks/PHP/clancats/app/config/main.config.php

@@ -0,0 +1,27 @@
+<?php 
+/*
+ *---------------------------------------------------------------
+ * Main CCF configuration
+ *---------------------------------------------------------------
+ *
+ * Take a look at the core main configuration file to see 
+ * what options are around. .../CCF/vendor/clancats/core/config/main.config.php
+ */
+return array(
+	
+	/*
+	 * URL configuration
+	 */
+	'url'	=> array(
+		// if not in the root directory set the path offset.
+		'path'		=> '/',
+	),
+	
+	/*
+	 * Security
+	 */
+	'security' => array(
+		// it is really important that you choose your own one!
+		'salt' => '7Q[„YI[œ1<-2S3Ck[%¼Sz59vQ!sl1aœÃ',
+	),
+);

+ 107 - 0
frameworks/PHP/clancats/app/config/router.config.php

@@ -0,0 +1,107 @@
+<?php 
+/*
+ *---------------------------------------------------------------
+ * Router map configuration
+ *---------------------------------------------------------------
+ *
+ * You can use this configuration to set you default application
+ * routes.
+ */
+return array(
+
+	/*
+	 * Not Found and internal Server Error
+	 */
+	'#404'	=> 'Error@404',
+	'#500'	=> 'Error@500',
+
+	/**
+	 * Plaintext response benchmark
+	 */
+	'plaintext' => function()
+	{
+		$response = CCResponse::create("Hello, World!", 200);
+		$response->header("Content-Type", "text/plain; charset=UTF-8");
+		return $response;
+ 	},
+       	
+	/**
+	 * JSON response benchmark
+	 */
+	'json' => function() 
+	{
+		return CCResponse::create( json_encode(
+			array('message' => 'Hello, World!')
+		), 200 )->header( 'Content-Type', 'application/json' );
+	},
+
+	
+	/**
+	 * DB response benchmark
+	 */
+	'db' => function() 
+	{		
+		$world = DB::select( 'World' )->find( mt_rand(1, 10000) );
+		$world->id = intval($world->id);
+		$world->randomNumber = intval($world->randomNumber);
+		return CCResponse::create( json_encode( $world), 200 )
+			->header( 'Content-Type', 'application/json' );
+	},
+	
+	/**
+	 * Qeuries response benchmark
+	 */
+	'queries' => function() 
+	{		
+		$queries = CCIn::get( 'queries', 1 );
+		if ($queries < 1) {
+			$queries = 1;
+	        }  
+	        if ($queries > 500) {
+			$queries = 500;
+		}	
+                $worlds = array();
+		
+		for($i = 0; $i < $queries; ++$i) 
+		{
+			$world = DB::select( 'World' )->find( mt_rand(1, 10000) );
+			$world->id = intval($world->id);
+			$world->randomNumber = intval($world->randomNumber);
+			$worlds[] = $world;
+		}
+		return CCResponse::create( json_encode( $worlds), 200 )
+			->header( 'Content-Type', 'application/json' );
+	},
+
+	/**
+	 * Updates response benchmark
+	 */
+	'updates' => function() 
+	{		
+		$queries = CCIn::get( 'queries', 1 );
+		if ($queries < 1) {
+			$queries = 1;
+	        }  
+	        if ($queries > 500) {
+			$queries = 500;
+		}	
+                $worlds = array();
+		
+		for($i = 0; $i < $queries; ++$i) 
+		{
+			$id = mt_rand(1, 10000);
+			DB::update( 'World' )
+				->set( 'randomNumber', mt_rand(1, 10000) )
+				->where( 'id', $id )
+				->run(); 
+			$world = DB::select( 'World' )->find( $id );
+			$world->id = intval($world->id);
+			$world->randomNumber = intval($world->randomNumber);
+			$worlds[] = $world;
+		}
+		return CCResponse::create( json_encode( $worlds), 200 )
+			->header( 'Content-Type', 'application/json' );
+	},
+	
+	'fortunes' => 'Bench@fortunes',
+);

+ 33 - 0
frameworks/PHP/clancats/app/controllers/BenchController.php

@@ -0,0 +1,33 @@
+<?php
+class BenchController extends CCController 
+{	
+	/**
+	 * Sign out action
+	 */
+	public function action_fortunes() 
+	{
+		$view = CCView::create( 'bench/fortune' );
+		
+		$fortunes = DB::select( 'Fortune' )->run();
+		
+		$runtimeFortune = new stdClass;
+		$runtimeFortune->id = 0;
+		$runtimeFortune->message = 'Additional fortune added at request time.';
+		
+		$fortunes[] = $runtimeFortune;
+		
+		usort($fortunes, function($left, $right) {
+			if ($left->message === $right->message) {
+				return 0;
+			} else if ($left->message > $right->message) {
+				return 1;
+			} else {
+				return -1;
+			}
+		});
+		
+		$view->fortunes = $fortunes;
+		
+		return CCResponse::create( $view->render() );
+	}
+}

+ 24 - 0
frameworks/PHP/clancats/app/views/bench/fortune.php

@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<title>Fortunes</title>
+</head>
+<body>
+
+<table>
+	<tr>
+		<th>id</th>
+		<th>message</th>
+	</tr>
+
+	<?php foreach($fortunes as $fortune): ?>
+	<tr>
+		<td><?php echo $fortune->id; ?></td>
+		<td><?php echo htmlspecialchars($fortune->message); ?></td>
+	</tr>
+	<?php endforeach; ?>
+
+</table>
+
+</body>
+</html>

+ 28 - 0
frameworks/PHP/clancats/benchmark_config.json

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

+ 25 - 0
frameworks/PHP/clancats/composer.json

@@ -0,0 +1,25 @@
+{
+	"name": "clancats/framework",
+	"description": "ClanCats Framework, because your time is precious. HMVC PHP framework.",
+	"homepage": "http://www.clancats.io",
+	"keywords": ["ccf", "framework", "clancats"],
+	"license": "MIT",
+	"require": {
+		"clancats/core": "2.0.*"
+	},
+	"config": {
+		"vendor-dir": "CCF/vendor"
+	},
+	"scripts": {
+		"post-install-cmd": [
+			"php cli phpunit::build"
+		],
+		"post-update-cmd": [
+			"php cli phpunit::build"
+		],
+		"post-create-project-cmd": [
+			"php cli doctor::security_key"
+		]
+	},
+	"minimum-stability": "stable"
+}

+ 43 - 0
frameworks/PHP/clancats/deploy/nginx.conf

@@ -0,0 +1,43 @@
+worker_processes  8;
+
+error_log stderr error;
+
+events {
+	worker_connections  1024;
+}
+
+http {
+	include       /usr/local/nginx/conf/mime.types;
+	default_type  application/octet-stream;
+
+	access_log off;
+
+	sendfile        on;
+	keepalive_timeout  65;
+
+	upstream fastcgi_backend {
+		server 127.0.0.1:9001;
+		keepalive 32;
+	}
+
+	server {
+		listen       8080;
+		server_name  localhost;
+
+		root /home/ubuntu/FrameworkBenchmarks/;
+		index  index.php;
+
+		location / {
+			try_files $uri $uri/ /index.php?$uri&$args;
+		}
+
+		location ~ \.php$ {
+			try_files $uri =404;
+			fastcgi_pass   fastcgi_backend;
+			fastcgi_keep_conn on;
+			fastcgi_index  index.php;
+			fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
+			include        /usr/local/nginx/conf/fastcgi_params;
+		}
+	}
+}

+ 9 - 0
frameworks/PHP/clancats/deploy/php-clancatsframework

@@ -0,0 +1,9 @@
+<VirtualHost *:8080>
+  Alias /php-fuel/ "/home/ubuntu/FrameworkBenchmarks/php-clancatsframework/public/"
+  <Directory /home/ubuntu/FrameworkBenchmarks/php-clancatsframework/public/>
+		  Options Indexes FollowSymLinks MultiViews
+		  #AllowOverride None
+		  Order allow,deny
+		  allow from all
+  </Directory>
+</VirtualHost>

+ 1 - 0
frameworks/PHP/clancats/deploy/php-fpm.pid

@@ -0,0 +1 @@
+18981

+ 32 - 0
frameworks/PHP/clancats/index.php

@@ -0,0 +1,32 @@
+<?php 
+/*
+ *---------------------------------------------------------------
+ * ClanCatsFramework runner
+ *---------------------------------------------------------------
+ *
+ * This file just loads CCF and all needed resources to run the 
+ * php unit tests. PHPUnit is a really elegant way to make sure 
+ * that everything works how it should.
+ *
+ *---------------------------------------------------------------
+ * Require CCF
+ *---------------------------------------------------------------
+ *
+ * load the framework file wich wil initialize CCF. 
+ */
+require_once __DIR__."/clancatsapp/framework.php";
+
+/*
+ * execute the main request
+ * The main request contains the params of the http header
+ */
+$response = CCRequest::uri( CCServer::uri() )
+    ->perform()
+    ->response();
+
+/*
+ * "send" means actaully printing the response.
+ * If the secound parameter is true the response will 
+ * also set headers
+ */
+$response->send( true );

Some files were not shown because too many files changed in this diff