Browse Source

Merge branch 'master' into fortune-page

Martin Tzvetanov Grigorov 11 years ago
parent
commit
add2df2ac1
93 changed files with 1833 additions and 374 deletions
  1. BIN
      UrWeb/bench.exe
  2. 1 1
      UrWeb/bench.ur
  3. 1 1
      UrWeb/setup.py
  4. 1 0
      beego/setup.py
  5. 1 1
      config/benchmark_profile
  6. 8 8
      dart-start/README.md
  7. 9 8
      dart-start/pubspec.yaml
  8. 24 24
      dart-start/server.dart
  9. 1 1
      dart-start/setup.py
  10. 7 7
      dart-stream/README.md
  11. 9 6
      dart-stream/pubspec.yaml
  12. 16 14
      dart-stream/server.dart
  13. 1 1
      dart-stream/setup.py
  14. 6 6
      dart/README.md
  15. 2 0
      dart/pubspec.yaml
  16. 1 1
      dart/server.dart
  17. 1 1
      dart/setup.py
  18. 2 2
      netty/README.md
  19. 1 1
      netty/benchmark_config
  20. 25 25
      netty/pom.xml
  21. 2 2
      netty/setup.py
  22. 78 91
      netty/src/main/java/hello/HelloServerHandler.java
  23. 2 13
      netty/src/main/java/hello/HelloServerInitializer.java
  24. 16 7
      netty/src/main/java/hello/HelloWebServer.java
  25. 20 0
      ninja-standalone/.gitignore
  26. 26 0
      ninja-standalone/README.md
  27. 0 0
      ninja-standalone/__init__.py
  28. 28 0
      ninja-standalone/benchmark_config
  29. 163 0
      ninja-standalone/pom.xml
  30. 23 0
      ninja-standalone/setup.py
  31. 35 0
      ninja-standalone/source_code
  32. 26 0
      ninja-standalone/src/main/java/conf/Routes.java
  33. 50 0
      ninja-standalone/src/main/java/hello/controllers/HelloDbController.java
  34. 28 0
      ninja-standalone/src/main/java/hello/controllers/HelloFortuneController.java
  35. 27 0
      ninja-standalone/src/main/java/hello/controllers/HelloJsonController.java
  36. 13 0
      ninja-standalone/src/main/java/hello/controllers/HelloPlaintextController.java
  37. 29 0
      ninja-standalone/src/main/java/hello/dao/FortuneDao.java
  38. 21 0
      ninja-standalone/src/main/java/hello/dao/WorldDao.java
  39. 36 0
      ninja-standalone/src/main/java/hello/model/Fortune.java
  40. 14 0
      ninja-standalone/src/main/java/hello/model/World.java
  41. 20 0
      ninja-standalone/src/main/java/hello/views/HelloFortuneController/index.ftl.html
  42. 45 0
      ninja-standalone/src/main/resources/META-INF/persistence.xml
  43. 38 0
      ninja-standalone/src/main/resources/conf/application.conf
  44. 17 0
      ninja-standalone/src/main/resources/conf/messages.properties
  45. 15 0
      ninja-standalone/src/main/resources/ehcache.xml
  46. 14 0
      ninja-standalone/src/main/resources/logback.xml
  47. 13 0
      ninja-standalone/src/main/webapp/WEB-INF/resin-web.xml
  48. 32 0
      ninja-standalone/src/main/webapp/WEB-INF/web.xml
  49. 20 0
      ninja/.gitignore
  50. 26 0
      ninja/README.md
  51. 0 0
      ninja/__init__.py
  52. 27 0
      ninja/benchmark_config
  53. 157 0
      ninja/pom.xml
  54. 32 0
      ninja/setup.py
  55. 35 0
      ninja/source_code
  56. 26 0
      ninja/src/main/java/conf/Routes.java
  57. 50 0
      ninja/src/main/java/hello/controllers/HelloDbController.java
  58. 28 0
      ninja/src/main/java/hello/controllers/HelloFortuneController.java
  59. 27 0
      ninja/src/main/java/hello/controllers/HelloJsonController.java
  60. 13 0
      ninja/src/main/java/hello/controllers/HelloPlaintextController.java
  61. 29 0
      ninja/src/main/java/hello/dao/FortuneDao.java
  62. 21 0
      ninja/src/main/java/hello/dao/WorldDao.java
  63. 36 0
      ninja/src/main/java/hello/model/Fortune.java
  64. 14 0
      ninja/src/main/java/hello/model/World.java
  65. 20 0
      ninja/src/main/java/hello/views/HelloFortuneController/index.ftl.html
  66. 45 0
      ninja/src/main/resources/META-INF/persistence.xml
  67. 40 0
      ninja/src/main/resources/conf/application.conf
  68. 17 0
      ninja/src/main/resources/conf/messages.properties
  69. 15 0
      ninja/src/main/resources/ehcache.xml
  70. 14 0
      ninja/src/main/resources/logback.xml
  71. 13 0
      ninja/src/main/webapp/WEB-INF/resin-web.xml
  72. 32 0
      ninja/src/main/webapp/WEB-INF/web.xml
  73. 28 40
      openresty/app.lua
  74. 15 4
      openresty/nginx.conf
  75. 1 1
      rack/Gemfile-jruby
  76. 1 1
      rack/README.md
  77. 1 1
      rails-stripped/Gemfile-jruby
  78. 1 1
      rails-stripped/README.md
  79. 1 1
      rails/Gemfile-jruby
  80. 1 1
      rails/README.md
  81. 2 1
      revel-jet/benchmark_config
  82. 4 4
      revel-jet/src/benchmark/conf/app.conf
  83. 1 0
      revel-qbs/setup.py
  84. 3 0
      revel/setup.py
  85. 4 4
      revel/src/benchmark/conf/app.conf
  86. 1 1
      sinatra/Gemfile-jruby
  87. 1 1
      sinatra/README.md
  88. 10 10
      toolset/setup/linux/installer.py
  89. 1 1
      toolset/setup/windows/installer.ps1
  90. 2 3
      tornado/server.py
  91. 67 75
      vertx/WebServer.java
  92. 2 2
      vertx/app.js
  93. 1 1
      webgo/benchmark_config

BIN
UrWeb/bench.exe


+ 1 - 1
UrWeb/bench.ur

@@ -56,7 +56,7 @@ fun queries oqs =
 fun updates oqs =
   rows <- List.tabulateM (fn _ => n <- rand; world_find (clamp n)) (parseQueries oqs);
   rows' <- List.mapM (fn r => n <- rand; return (r -- #RandomNumber ++ {RandomNumber = clamp n})) rows;
-  u <- List.mapM (fn r => dml (UPDATE world SET RandomNumber = {[r.RandomNumber]} WHERE Id = {[r.Id]})) rows';
+  List.app (fn r => dml (UPDATE world SET RandomNumber = {[r.RandomNumber]} WHERE Id = {[r.Id]})) rows';
   returnJson rows'
 
 table fortune : {Id : int, Message : string} PRIMARY KEY Id

+ 1 - 1
UrWeb/setup.py

@@ -10,7 +10,7 @@ def start(args, logfile, errfile):
                 'password=benchmarkdbpass '
                 'host=' + args.database_host)
   env = {'URWEB_PQ_CON': conn_string}
-  subprocess.Popen("./bench.exe -t " + threads,
+  subprocess.Popen("./bench.exe -k -t " + threads,
                    env=env, shell=True, cwd="UrWeb", stderr=errfile, stdout=logfile)
   return 0
 

+ 1 - 0
beego/setup.py

@@ -8,6 +8,7 @@ def start(args, logfile, errfile):
     subprocess.call("set GOPATH=C:\\FrameworkBenchmarks\\beego&&go get ./...", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
     subprocess.Popen("setup.bat", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
     return 0
+  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/beego')
   subprocess.call("go get ./...", shell=True, cwd="beego", stderr=errfile, stdout=logfile)
   subprocess.Popen("go run src/hello/hello.go".rsplit(" "), cwd="beego", stderr=errfile, stdout=logfile)
   return 0

+ 1 - 1
config/benchmark_profile

@@ -1,7 +1,7 @@
 export JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-amd64
 export RESIN_HOME=~/FrameworkBenchmarks/installs/resin-4.0.36
 export GRAILS_HOME=~/FrameworkBenchmarks/installs/grails-2.3.3
-export VERTX_HOME=~/FrameworkBenchmarks/installs/vert.x-2.1M1
+export VERTX_HOME=~/FrameworkBenchmarks/installs/vert.x-2.1M2
 export GOROOT=~/FrameworkBenchmarks/installs/go
 export GOPATH=~/FrameworkBenchmarks/go:~/FrameworkBenchmarks/webgo:~/FrameworkBenchmarks/revel
 export TOMCAT_HOME=~/FrameworkBenchmarks/installs/apache-tomcat-7.0.35

+ 8 - 8
dart-start/README.md

@@ -4,14 +4,14 @@ This test adds [Start](https://github.com/lvivski/start), a Sinatra inspired web
 
 ## Versions
 
-* [Dart SDK version 0.8.1.2_r28355](https://launchpad.net/~hachre/+archive/dart)
-* [Dart args version 0.8.1](http://pub.dartlang.org/packages/args)
-* [Dart crypto version 0.8.1](http://pub.dartlang.org/packages/crypto)
-* [Dart mustache version 0.1.5](http://pub.dartlang.org/packages/mustache)
-* [Dart mongo_dart version 0.1.30](http://pub.dartlang.org/packages/mongo_dart)
-* [Dart postgresql version 0.2.8](http://pub.dartlang.org/packages/postgresql)
-* [Dart start version 0.0.9+1](http://pub.dartlang.org/packages/start)
-* [Dart yaml version 0.8.1](http://pub.dartlang.org/packages/yaml)
+* [Dart SDK version 1.0.0.7_r30338](https://launchpad.net/~hachre/+archive/dart)
+* [Dart args version 0.9.0](http://pub.dartlang.org/packages/args)
+* [Dart crypto version 0.9.0](http://pub.dartlang.org/packages/crypto)
+* [Dart mustache version 0.1.6](http://pub.dartlang.org/packages/mustache)
+* [Dart mongo_dart version 0.1.35](http://pub.dartlang.org/packages/mongo_dart)
+* [Dart postgresql version 0.2.12](http://pub.dartlang.org/packages/postgresql)
+* [Dart start version 0.1.1](http://pub.dartlang.org/packages/start)
+* [Dart yaml version 0.9.0](http://pub.dartlang.org/packages/yaml)
 
 ## Test URLs
 

+ 9 - 8
dart-start/pubspec.yaml

@@ -1,11 +1,12 @@
 name: DartStartBenchmark
 description: A benchmark of Dart Start, a Sinatra inspired web framework
+environment:
+  sdk: ">=0.8.10+6 <2.0.0"
 dependencies:
-  args: 0.8.1
-  crypto: 0.8.1
-  mongo_dart: 0.1.30
-  mustache: 0.1.5
-  postgresql: 0.2.8
-  start: 0.0.9+1
-  yaml: 0.8.1
-
+  args: 0.9.0
+  crypto: 0.9.0
+  mongo_dart: 0.1.35
+  mustache: 0.1.6
+  postgresql: 0.2.12
+  start: 0.1.1
+  yaml: 0.9.0

+ 24 - 24
dart-start/server.dart

@@ -1,7 +1,7 @@
 import "dart:core";
 import "dart:io";
 import 'dart:async' show Future;
-import 'dart:json' as json;
+import 'dart:convert';
 import 'dart:math' show Random;
 import "package:start/start.dart";
 import "package:args/args.dart";
@@ -53,13 +53,13 @@ class World {
   toJson() => { "id": id, "randomnumber": randomnumber };
 }
 
-main() {
+main(List<String> args) {
   var parser = new ArgParser();
   parser.addOption('address', abbr: 'a', defaultsTo: '0.0.0.0');
   parser.addOption('port', abbr: 'p', defaultsTo: '8080');
   parser.addOption('dbconnections', abbr: 'd', defaultsTo: '256');
   
-  var arguments = parser.parse(new Options().arguments);
+  var arguments = parser.parse(args);
   
   Future.wait([
     new File("postgresql.yaml").readAsString().then((config){
@@ -93,7 +93,7 @@ main() {
           };
           
           _setJsonHeaders(request.response);
-          request.response.send(json.stringify(helloWorld));
+          request.response.send(JSON.encode(helloWorld));
         });
         
         
@@ -103,7 +103,7 @@ main() {
           _setJsonHeaders(request.response);
           
           _query().then((data) {
-            request.response.send(json.stringify(data));
+            request.response.send(JSON.encode(data));
           });
         });
         
@@ -121,7 +121,7 @@ main() {
                   growable: false
                 )
             )
-            .then((response) => request.response.send(json.stringify(response)));
+            .then((response) => request.response.send(JSON.encode(response)));
         });
         
         // Fortunes test
@@ -129,7 +129,7 @@ main() {
           _setHtmlHeaders(request.response);
           
           _connectionPool.connect().then((connection) {
-            return connection.query('SELECT "id", "message" FROM "Fortune";')
+            return connection.query('SELECT id, message FROM fortune;')
                 .map((row) => new Fortune(row[0], row[1]))
                 .toList()
                 .whenComplete(() { connection.close(); });
@@ -159,7 +159,7 @@ main() {
                   return _connectionPool.connect()
                       .then((connection) {
                         return connection.execute(
-                              'UPDATE "World" SET "randomnumber" = @randomnumber WHERE "id" = @id;',
+                              'UPDATE world SET randomnumber = @randomnumber WHERE id = @id;',
                               { 
                                 'randomnumber': world.randomnumber,
                                 'id': world.id 
@@ -170,7 +170,7 @@ main() {
                       .then((_) => world);
                 });
           }, growable: false))
-          .then((worlds) => request.response.send(json.stringify(worlds)));
+          .then((worlds) => request.response.send(JSON.encode(worlds)));
         });
         
         // Plain text test
@@ -186,8 +186,8 @@ main() {
             .then((_) {
               var collectionData = new List.generate(_WORLD_TABLE_SIZE, (index) {
                 return {
-                  "id": index + 1,
-                  "randomnumber": _RANDOM.nextInt(_WORLD_TABLE_SIZE)
+                  "_id": index + 1,
+                  "randomNumber": _RANDOM.nextInt(_WORLD_TABLE_SIZE)
                 };
               });
               return _worldCollection.insertAll(collectionData); 
@@ -205,7 +205,7 @@ main() {
                 var hash = new MD5();
                 hash.add(_RANDOM.nextInt(_FORTUNE_TABLE_SIZE).toString().codeUnits);
                 return {
-                  "id": index + 1,
+                  "_id": index + 1,
                   "message": CryptoUtils.bytesToHex(hash.close())
                 };
               });
@@ -224,8 +224,8 @@ main() {
 
           _mongoQuery().then((data) {
             request.response.json({
-              "id": data["id"],
-              "randomnumber": data["randomnumber"]
+              "id": data["_id"],
+              "randomnumber": data["randomNumber"]
             });
           });
         });
@@ -247,11 +247,11 @@ main() {
             .then((response) {
               var results = response.map((world) {
                 return {
-                  "id": world["id"],
-                  "randomnumber": world["randomnumber"]
+                  "id": world["_id"],
+                  "randomnumber": world["randomNumber"]
                 };
               });
-              request.response.send(json.stringify(results.toList()));
+              request.response.send(JSON.encode(results.toList()));
             });
         });
         
@@ -264,7 +264,7 @@ main() {
           Future.wait(new List.generate(queries, (index) {
             return _mongoQuery()
                 .then((world) {
-                  world["randomnumber"] = _RANDOM.nextInt(_WORLD_TABLE_SIZE);
+                  world["randomNumber"] = _RANDOM.nextInt(_WORLD_TABLE_SIZE);
                   return _worldCollection.update( { "_id": world["_id"] }, world)
                       .then((_) => world);
                 });
@@ -272,11 +272,11 @@ main() {
           .then((worlds) {
             var result = worlds.map((world) {
               return {
-                "id": world["id"],
-                "randomnumber": world["randomnumber"]
+                "id": world["_id"],
+                "randomNumber": world["randomNumber"]
               };
             });
-            request.response.send(json.stringify(result.toList()));
+            request.response.send(JSON.encode(result.toList()));
           });
         });
         
@@ -288,7 +288,7 @@ main() {
           
           _fortuneCollection.find().toList().then((fortunes) {
             fortunes = fortunes.map((fortune) {
-              return new Fortune(fortune["id"], fortune["message"]);
+              return new Fortune(fortune["_id"], fortune["message"]);
             }).toList();
             fortunes.add(new Fortune(0, 'Additional fortune added at request time.'));
             fortunes.sort();
@@ -342,7 +342,7 @@ _parseQueriesParam(param) {
 _query() {
   return _connectionPool.connect().then((connection) {
     return connection
-      .query('SELECT "id", "randomnumber" FROM "World" WHERE id = @id;', { 'id': _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1 })
+      .query('SELECT id, randomnumber FROM world WHERE id = @id;', { 'id': _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1 })
       .single
       .then((row) =>new World(row[0], row[1]))
       .whenComplete(() {
@@ -354,6 +354,6 @@ _query() {
 // runs a mongo query and returns a promise
 _mongoQuery() {
   return _worldCollection.findOne({
-    "id": _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1
+    "_id": _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1
   });
 }

+ 1 - 1
dart-start/setup.py

@@ -10,7 +10,7 @@ def start(args, logfile, errfile):
     #
     # install dart dependencies
     #
-    subprocess.check_call('pub install', shell=True, cwd='dart-start', stderr=errfile, stdout=logfile)
+    subprocess.check_call('pub upgrade', shell=True, cwd='dart-start', stderr=errfile, stdout=logfile)
     #
     # start dart servers
     #

+ 7 - 7
dart-stream/README.md

@@ -4,13 +4,13 @@ This test adds [Stream](https://github.com/rikulo/stream), a lightweight Dart we
 
 ## Versions
 
-* [Dart SDK version 0.8.1.2_r28355](https://launchpad.net/~hachre/+archive/dart)
-* [Dart args version 0.8.1](http://pub.dartlang.org/packages/args)
-* [Dart crypto version 0.8.1](http://pub.dartlang.org/packages/crypto)
-* [Dart mongo_dart version 0.1.30](http://pub.dartlang.org/packages/mongo_dart)
-* [Dart postgresql version 0.2.8](http://pub.dartlang.org/packages/postgresql)
-* [Dart stream version 0.8.4](http://pub.dartlang.org/packages/start)
-* [Dart yaml version 0.8.1](http://pub.dartlang.org/packages/yaml)
+* [Dart SDK version 1.0.0.3_r30188](https://launchpad.net/~hachre/+archive/dart)
+* [Dart args version 0.9.0](http://pub.dartlang.org/packages/args)
+* [Dart crypto version 0.9.0](http://pub.dartlang.org/packages/crypto)
+* [Dart mongo_dart version 0.1.35](http://pub.dartlang.org/packages/mongo_dart)
+* [Dart postgresql version 0.2.12](http://pub.dartlang.org/packages/postgresql)
+* [Dart stream version 1.0.0](http://pub.dartlang.org/packages/start)
+* [Dart yaml version 0.9.0](http://pub.dartlang.org/packages/yaml)
 
 ## Test URLs
 

+ 9 - 6
dart-stream/pubspec.yaml

@@ -1,9 +1,12 @@
 name: DartStreamBenchmark
 description: A benchmark for Stream, a lightweight Dart web server
+environment:
+  sdk: '>=0.8.7'
 dependencies:
-  args: 0.8.1
-  crypto: 0.8.1
-  mongo_dart: 0.1.30
-  postgresql: 0.2.8
-  stream: 0.8.4
-  yaml: 0.8.1
+  args: 0.9.0
+  crypto: 0.9.0
+  mongo_dart: 0.1.35
+  postgresql: 0.2.12
+  rikulo_commons: 1.0.0
+  stream: 1.0.0
+  yaml: 0.9.0

+ 16 - 14
dart-stream/server.dart

@@ -3,7 +3,7 @@ library stream_benchmark;
 import "dart:core";
 import "dart:io";
 import 'dart:async' show Future;
-import 'dart:json' as json;
+import 'dart:convert';
 import 'dart:math' show Random;
 import "package:stream/stream.dart";
 import "package:args/args.dart";
@@ -84,13 +84,15 @@ class World {
   toJson() => { "id": id, "randomNumber": randomnumber };
 }
 
-main() {
+main(List<String> args) {
+  
   var parser = new ArgParser();
   parser.addOption('address', abbr: 'a', defaultsTo: '0.0.0.0');
   parser.addOption('port', abbr: 'p', defaultsTo: '8080');
   parser.addOption('dbconnections', abbr: 'd', defaultsTo: '256');
   
-  var arguments = parser.parse(new Options().arguments);
+  var arguments = parser.parse(args);
+  
   Future.wait([
      new File("postgresql.yaml").readAsString().then((config){
        _connectionPool = new pgpool.Pool(
@@ -118,13 +120,13 @@ _jsonTest(HttpConnect connect) {
       "message": "Hello, World!"
   };
   
-  connect.response.write(json.stringify(helloWorld));
+  connect.response.write(JSON.encode(helloWorld));
 }
 
 _dbTest(HttpConnect connect) {
   
   return _query().then((data) {
-    connect.response.write(json.stringify(data));
+    connect.response.write(JSON.encode(data));
   });
 }
 
@@ -138,7 +140,7 @@ _queriesTest(HttpConnect connect) {
             growable: false
         )
     )
-    .then((response) => connect.response.write(json.stringify(response)));
+    .then((response) => connect.response.write(JSON.encode(response)));
 }
 
 _updatesTest(HttpConnect connect) {
@@ -151,7 +153,7 @@ _updatesTest(HttpConnect connect) {
             return _connectionPool.connect()
               .then((connection) {
                 return connection.execute(
-                      'UPDATE "World" SET "randomnumber" = @randomnumber WHERE "id" = @id;',
+                      'UPDATE world SET randomnumber = @randomnumber WHERE id = @id;',
                       { 
                         'randomnumber': world.randomnumber,
                         'id': world.id 
@@ -162,13 +164,13 @@ _updatesTest(HttpConnect connect) {
                 .then((_) => world);
           });
     }, growable: false))
-    .then((worlds) => connect.response.write(json.stringify(worlds)));
+    .then((worlds) => connect.response.write(JSON.encode(worlds)));
 }
 
 _fortunesTest(HttpConnect connect) {
   
   return _connectionPool.connect().then((connection) {
-    return connection.query('SELECT "id", "message" FROM "Fortune";')
+    return connection.query('SELECT id, message FROM fortune;')
         .map((row) => new Fortune(row[0], row[1]))
           .toList()
             .whenComplete(() { connection.close(); });
@@ -187,7 +189,7 @@ _plaintextTest(HttpConnect connect) {
 _dbMongoTest(HttpConnect connect) {
   
   return _mongoQuery().then((data) {
-    connect.response.write(json.stringify({
+    connect.response.write(JSON.encode({
       "id": data["_id"],
       "randomNumber": data["randomNumber"]
     }));
@@ -211,7 +213,7 @@ _queriesMongoTest(HttpConnect connect) {
           "randomNumber": world["randomNumber"]
         };
       });
-      connect.response.write(json.stringify(results.toList()));
+      connect.response.write(JSON.encode(results.toList()));
     });
 }
 
@@ -233,7 +235,7 @@ _updatesMongoTest(HttpConnect connect) {
           "randomNumber": world["randomNumber"]
         };
       });
-      connect.response.write(json.stringify(result.toList()));
+      connect.response.write(JSON.encode(result.toList()));
     });
 }
 
@@ -282,14 +284,14 @@ _htmlHeadersFilter(HttpConnect connect, Future chain(HttpConnect conn)) {
 
 // parse queries param
 _parseQueriesParam(param) {
-  return param.isEmpty ? 1 : int.parse(param, radix: 10, onError: (_) => 1).clamp(1, 500);
+  return (param == null || param.isEmpty) ? 1 : int.parse(param, radix: 10, onError: (_) => 1).clamp(1, 500);
 }
 
 // runs a query and returns a promise
 _query() {
   return _connectionPool.connect().then((connection) {
     return connection
-      .query('SELECT "id", "randomnumber" FROM "World" WHERE id = @id;', { 'id': _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1 })
+      .query('SELECT id, randomnumber FROM world WHERE id = @id;', { 'id': _RANDOM.nextInt(_WORLD_TABLE_SIZE) + 1 })
       .single
       .then((row) =>new World(row[0], row[1]))
       .whenComplete(() {

+ 1 - 1
dart-stream/setup.py

@@ -10,7 +10,7 @@ def start(args, logfile, errfile):
     #
     # install dart dependencies
     #
-    subprocess.check_call('pub install', shell=True, cwd='dart-stream', stderr=errfile, stdout=logfile)
+    subprocess.check_call('pub upgrade', shell=True, cwd='dart-stream', stderr=errfile, stdout=logfile)
     #
     # start dart servers
     #

+ 6 - 6
dart/README.md

@@ -4,12 +4,12 @@ This is the dart portion of a [benchmarking test suite](../) comparing a variety
 
 ## Versions
 
-* [Dart SDK version 0.5.13.1_r23552](http://www.dartlang.org/)
-* [Dart args version 0.5.9](http://pub.dartlang.org/packages/args)
-* [Dart crypto version 0.5.13](http://pub.dartlang.org/packages/crypto)
-* [Dart mustache version 0.1.5](http://pub.dartlang.org/packages/mustache)
-* [Dart postgresql version 0.2.7](http://pub.dartlang.org/packages/postgresql)
-* [Dart yaml version 0.5.7](http://pub.dartlang.org/packages/yaml)
+* [Dart SDK version 1.0.0.7_r30338](http://www.dartlang.org/)
+* [Dart args version 0.9.0](http://pub.dartlang.org/packages/args)
+* [Dart crypto version 0.9.0](http://pub.dartlang.org/packages/crypto)
+* [Dart mustache version 0.1.6](http://pub.dartlang.org/packages/mustache)
+* [Dart postgresql version 0.2.12](http://pub.dartlang.org/packages/postgresql)
+* [Dart yaml version 0.9.0](http://pub.dartlang.org/packages/yaml)
 
 ## Test URLs
 

+ 2 - 0
dart/pubspec.yaml

@@ -1,5 +1,7 @@
 name: dartbenchmark
 description: A benchmark of dart
+environment:
+  sdk: '>=0.8.10+6 <2.0.0'
 dependencies:
   args: 0.9.0
   crypto: 0.9.0

+ 1 - 1
dart/server.dart

@@ -12,7 +12,7 @@ import 'package:yaml/yaml.dart' as yaml;
 /// address and port for incoming connections is configurable via command line
 /// arguments, as is the number of database connections to be maintained in the
 /// connection pool.
-main(args) {
+main(List<String> args) {
   var parser = new ArgParser();
   parser.addOption('address', abbr: 'a', defaultsTo: '0.0.0.0');
   parser.addOption('port', abbr: 'p', defaultsTo: '8080');

+ 1 - 1
dart/setup.py

@@ -9,7 +9,7 @@ def start(args, logfile, errfile):
     #
     # install dart dependencies
     #
-    subprocess.check_call('pub install', shell=True, cwd='dart', stderr=errfile, stdout=logfile)
+    subprocess.check_call('pub upgrade', shell=True, cwd='dart', stderr=errfile, stdout=logfile)
     #
     # start dart servers
     #

+ 2 - 2
netty/README.md

@@ -8,7 +8,7 @@ This is the netty portion of a [benchmarking test suite](../) comparing a variet
 ## Versions
 
 * [Java OpenJDK 1.7.0_09](http://openjdk.java.net/)
-* [Netty 4.0.0.Beta2](http://netty.io/)
+* [Netty 4.0.14.Beta1](http://netty.io/)
 
 ## References
 * https://github.com/netty/netty/tree/master/example/src/main/java/io/netty/example/http/snoop
@@ -17,4 +17,4 @@ This is the netty portion of a [benchmarking test suite](../) comparing a variet
 
 ### JSON Encoding Test
 
-    http://localhost:8080/json
+    http://localhost:8080/json

+ 1 - 1
netty/benchmark_config

@@ -3,7 +3,7 @@
   "tests": [{
     "default": {
       "setup_file": "setup",
-      "json_url": "/",
+      "json_url": "/json",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",

+ 25 - 25
netty/pom.xml

@@ -10,36 +10,36 @@
 
   <dependencies>
     <dependency>
-    	<groupId>io.netty</groupId>
-    	<artifactId>netty-codec-http</artifactId>
-    	<version>4.0.0.CR7</version>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-codec-http</artifactId>
+      <version>4.0.14.Beta1</version>
     </dependency>
-	 <dependency>
-		<groupId>com.fasterxml.jackson.core</groupId>
-		<artifactId>jackson-databind</artifactId>
-		<version>2.1.1</version>
-	</dependency>
     <dependency>
-        <groupId>org.javassist</groupId>
-        <artifactId>javassist</artifactId>
-        <version>3.18.0-GA</version>
+      <groupId>com.fasterxml.jackson.core</groupId>
+      <artifactId>jackson-databind</artifactId>
+      <version>2.1.1</version>
+    </dependency>
+    <dependency>
+      <groupId>org.javassist</groupId>
+      <artifactId>javassist</artifactId>
+      <version>3.18.0-GA</version>
     </dependency>
   </dependencies>
   
   <build>
     <plugins>
-			<plugin>
-				<inherited>true</inherited>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<version>2.3.2</version>
-				<configuration>
-					<source>1.7</source>
-					<target>1.7</target>
-					<optimize>true</optimize>
-					<debug>false</debug>
-				</configuration>
-			</plugin>
+      <plugin>
+        <inherited>true</inherited>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>2.3.2</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+          <optimize>true</optimize>
+          <debug>false</debug>
+        </configuration>
+      </plugin>
       <plugin>
         <artifactId>maven-assembly-plugin</artifactId>
         <configuration>
@@ -62,6 +62,6 @@
           </execution>
         </executions>
       </plugin>
-       </plugins>
+    </plugins>
   </build>
-</project>
+</project>

+ 2 - 2
netty/setup.py

@@ -6,7 +6,7 @@ import os
 def start(args, logfile, errfile):
   try:
     subprocess.check_call("mvn clean compile assembly:single", shell=True, cwd="netty", stderr=errfile, stdout=logfile)
-    subprocess.Popen("java -Dio.netty.noResourceLeakDetection=true -jar netty-example-0.1-jar-with-dependencies.jar".rsplit(" "), cwd="netty/target", stderr=errfile, stdout=logfile)
+    subprocess.Popen("java -jar netty-example-0.1-jar-with-dependencies.jar".rsplit(" "), cwd="netty/target", stderr=errfile, stdout=logfile)
     return 0
   except subprocess.CalledProcessError:
     return 1
@@ -20,4 +20,4 @@ def stop(logfile, errfile):
       if 'netty-example' in line:
         pid = int(line.split(None, 2)[1])
         os.kill(pid, 9)
-  return 0
+  return 0

+ 78 - 91
netty/src/main/java/hello/HelloServerHandler.java

@@ -2,135 +2,122 @@ package hello;
 
 import io.netty.buffer.ByteBuf;
 import io.netty.buffer.Unpooled;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+import com.fasterxml.jackson.databind.*;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.MessageList;
 import io.netty.channel.SimpleChannelInboundHandler;
-import io.netty.handler.codec.http.Cookie;
-import io.netty.handler.codec.http.CookieDecoder;
 import io.netty.handler.codec.http.DefaultFullHttpResponse;
 import io.netty.handler.codec.http.FullHttpResponse;
 import io.netty.handler.codec.http.HttpHeaders;
 import io.netty.handler.codec.http.HttpRequest;
-import io.netty.handler.codec.http.HttpResponse;
-import io.netty.handler.codec.http.ServerCookieEncoder;
-
-import java.util.Map;
-import java.util.HashMap;
-import java.util.Set;
-
-import java.io.*;
-
-import com.fasterxml.jackson.databind.*;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import io.netty.handler.codec.http.HttpVersion;
 import io.netty.util.CharsetUtil;
 
-import static io.netty.handler.codec.http.HttpHeaders.Names.*;
-import static io.netty.handler.codec.http.HttpHeaders.*;
-import static io.netty.handler.codec.http.HttpResponseStatus.*;
-import static io.netty.handler.codec.http.HttpVersion.*;
 
-public class HelloServerHandler extends SimpleChannelInboundHandler<Object>{
+public class HelloServerHandler extends SimpleChannelInboundHandler<Object> {
+    private final SimpleDateFormat format = new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z");
+    private CharSequence date;
 
-    /** Buffer that stores the response content */
-    private static final ObjectMapper mapper = new ObjectMapper();
+    private static final ObjectMapper MAPPER = new ObjectMapper();
+    private final ByteBuf buffer = Unpooled.directBuffer().writeBytes("Hello, World!".getBytes(CharsetUtil.UTF_8));
+    private final CharSequence contentLength = HttpHeaders.newEntity(String.valueOf(buffer.readableBytes()));
 
-    private MessageList<Object> out;
+    private static final CharSequence TYPE_PLAIN = HttpHeaders.newEntity("text/plain; charset=UTF-8");
+    private static final CharSequence TYPE_JSON = HttpHeaders.newEntity("application/json; charset=UTF-8");
 
-    @Override
-    public void beginMessageReceived(ChannelHandlerContext ctx) throws Exception {
-        out = MessageList.newInstance();
-        super.beginMessageReceived(ctx);
-    }
+    private static final CharSequence SERVER_NAME = HttpHeaders.newEntity("Netty");
+    private static final CharSequence CONTENT_TYPE_ENTITY = HttpHeaders.newEntity(HttpHeaders.Names.CONTENT_TYPE);
+    private static final CharSequence DATE_ENTITY = HttpHeaders.newEntity(HttpHeaders.Names.DATE);
+    private static final CharSequence CONTENT_LENGTH_ENTITY = HttpHeaders.newEntity(HttpHeaders.Names.CONTENT_LENGTH);
+    private static final CharSequence SERVER_ENTITY = HttpHeaders.newEntity(HttpHeaders.Names.SERVER);
 
     @Override
-    public void messageReceived(ChannelHandlerContext ctx, Object msg) throws Exception {
+    public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
         if (msg instanceof HttpRequest) {
             HttpRequest request = (HttpRequest) msg;
-
-            if (is100ContinueExpected(request)) {
-                send100Continue(out);
+            String uri = request.getUri();
+            switch (uri) {
+                case "/plaintext":
+                    writeResponse(ctx, request, buffer.duplicate().retain(), TYPE_PLAIN, contentLength);
+                    return;
+                case "/json":
+                    byte[] json = MAPPER.writeValueAsBytes(Collections.singletonMap("message", "Hello, World!"));
+                    writeResponse(ctx, request, ctx.alloc().buffer(json.length).writeBytes(json), TYPE_JSON,
+                            String.valueOf(json.length));
+                    return;
             }
-            ByteBuf buf = ctx.alloc().buffer();
-            if("/plaintext".equals(request.getUri())) {
-                buf.writeBytes("Hello, World!".getBytes(CharsetUtil.UTF_8));
-            } else {
-                Map<String, String> data = new HashMap<String, String>();
-                data.put("message", "Hello, world");
-
-                try
-                {
-                  buf.writeBytes(HelloServerHandler.mapper.writeValueAsBytes(data));
-                }
-                catch (IOException ex)
-                {
-                  // do nothing
-                }
-            }
-            writeResponse(ctx, request, buf, out);
+            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND, Unpooled.EMPTY_BUFFER, false);
+            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
         }
     }
 
-    private void writeResponse(ChannelHandlerContext ctx, HttpRequest request, ByteBuf buf, MessageList<Object> out) {
+    private void writeResponse(ChannelHandlerContext ctx, HttpRequest request, ByteBuf buf,
+                               CharSequence contentType, CharSequence contentLength) {
         // Decide whether to close the connection or not.
-        boolean keepAlive = isKeepAlive(request);
+        boolean keepAlive = HttpHeaders.isKeepAlive(request);
         // Build the response object.
         FullHttpResponse response = new DefaultFullHttpResponse(
-                HTTP_1_1, OK, buf);
-
-        response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
+                HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf, false);
+        HttpHeaders headers = response.headers();
+        headers.set(CONTENT_TYPE_ENTITY, contentType);
+        headers.set(SERVER_ENTITY, SERVER_NAME);
+        headers.set(DATE_ENTITY, date);
 
         if (keepAlive) {
-            // Add 'Content-Length' header only for a keep-alive connection.
-            response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
-            // Add keep alive header as per:
-            // - http://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01.html#Connection
-            response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
-        }
-
-        // Encode the cookie.
-        String cookieString = request.headers().get(COOKIE);
-        if (cookieString != null) {
-            Set<Cookie> cookies = CookieDecoder.decode(cookieString);
-            if (!cookies.isEmpty()) {
-                // Reset the cookies if necessary.
-                for (Cookie cookie: cookies) {
-                    response.headers().add(SET_COOKIE, ServerCookieEncoder.encode(cookie));
-                }
-            }
-        } else {
-            // Browser sent no cookie. Add some.
-            response.headers().add(SET_COOKIE, ServerCookieEncoder.encode("key1", "value1"));
-            response.headers().add(SET_COOKIE, ServerCookieEncoder.encode("key2", "value2"));
+            headers.set(CONTENT_LENGTH_ENTITY, contentLength);
         }
 
-        // Write the response.
-        out.add(response);
-
         // Close the non-keep-alive connection after the write operation is done.
         if (!keepAlive) {
-            this.out = MessageList.newInstance();
-            ctx.write(out).addListener(ChannelFutureListener.CLOSE);
+            ctx.write(response).addListener(ChannelFutureListener.CLOSE);
+        } else {
+            ctx.write(response, ctx.voidPromise());
         }
     }
 
-    private void send100Continue(MessageList<Object> out) {
-        HttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, CONTINUE, Unpooled.EMPTY_BUFFER);
-        out.add(response);
+    @Override
+    public void exceptionCaught(
+            ChannelHandlerContext ctx, Throwable cause) throws Exception {
+        ctx.close();
     }
 
     @Override
-    public void endMessageReceived(ChannelHandlerContext ctx) throws Exception {
-        if (out != null) {
-            MessageList<Object> msgs = out;
-            this.out = null;
-            ctx.write(msgs);
-        }
+    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
+        ctx.flush();
     }
 
     @Override
-    public void exceptionCaught(
-            ChannelHandlerContext ctx, Throwable cause) throws Exception {
-        cause.printStackTrace();
-        ctx.close();
+    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
+        super.handlerRemoved(ctx);
+        buffer.release();
+    }
+
+    @Override
+    public void channelActive(ChannelHandlerContext ctx) throws Exception {
+        date = HttpHeaders.newEntity(format.format(new Date()));
+
+        Channel channel = ctx.channel();
+        final ScheduledFuture<?> future = channel.eventLoop().scheduleWithFixedDelay(new Runnable() {
+            @Override
+            public void run() {
+                date = HttpHeaders.newEntity(format.format(new Date()));
+            }
+        }, 1000, 1000, TimeUnit.MILLISECONDS);
+
+        channel.closeFuture().addListener(new ChannelFutureListener() {
+            @Override
+            public void operationComplete(ChannelFuture channelFuture) throws Exception {
+                future.cancel(false);
+            }
+        });
     }
 }

+ 2 - 13
netty/src/main/java/hello/HelloServerInitializer.java

@@ -9,20 +9,9 @@ import io.netty.handler.codec.http.HttpResponseEncoder;
 public class HelloServerInitializer extends ChannelInitializer<SocketChannel> {
     @Override
     public void initChannel(SocketChannel ch) throws Exception {
-        // Create a default pipeline implementation.
         ChannelPipeline p = ch.pipeline();
-
-        // Uncomment the following line if you want HTTPS
-        //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
-        //engine.setUseClientMode(false);
-        //p.addLast("ssl", new SslHandler(engine));
-
-        p.addLast("decoder", new HttpRequestDecoder());
-        // Uncomment the following line if you don't want to handle HttpChunks.
-        //p.addLast("aggregator", new HttpObjectAggregator(1048576));
         p.addLast("encoder", new HttpResponseEncoder());
-        // Remove the following line if you don't want automatic content compression.
-        //p.addLast("deflater", new HttpContentCompressor());
+        p.addLast("decoder", new HttpRequestDecoder(4096, 8192, 8192, false));
         p.addLast("handler", new HelloServerHandler());
     }
-}
+}

+ 16 - 7
netty/src/main/java/hello/HelloWebServer.java

@@ -1,11 +1,19 @@
 package hello;
 
 import io.netty.bootstrap.ServerBootstrap;
+import io.netty.buffer.PooledByteBufAllocator;
 import io.netty.channel.Channel;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.EventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
+import io.netty.util.ResourceLeakDetector;
+
 
 public class HelloWebServer {
+    static {
+        ResourceLeakDetector.setEnabled(false);
+    }
 
     private final int port;
 
@@ -15,17 +23,18 @@ public class HelloWebServer {
 
     public void run() throws Exception {
         // Configure the server.
-        ServerBootstrap b = new ServerBootstrap();
-
+        EventLoopGroup group = new NioEventLoopGroup();
         try {
-            b.group(new NioEventLoopGroup(), new NioEventLoopGroup())
+            ServerBootstrap b = new ServerBootstrap();
+            b.group(group)
+             .childHandler(new HelloServerInitializer())
              .channel(NioServerSocketChannel.class)
-             .childHandler(new HelloServerInitializer());
-
+             .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
+             
             Channel ch = b.bind(port).sync().channel();
             ch.closeFuture().sync();
         } finally {
-            b.shutdown();
+            group.shutdownGracefully().sync();
         }
     }
 
@@ -38,4 +47,4 @@ public class HelloWebServer {
         }
         new HelloWebServer(port).run();
     }
-}
+}

+ 20 - 0
ninja-standalone/.gitignore

@@ -0,0 +1,20 @@
+.DS_Store
+*.pyc
+installs/
+*.log
+*.lock
+node_modules/
+*.war
+target/
+*.out
+*.class
+mods/
+/.settings
+/.buildpath
+/.project
+*.iml
+.idea/
+.hsenv/
+azure.err
+*~
+/.classpath

+ 26 - 0
ninja-standalone/README.md

@@ -0,0 +1,26 @@
+# Ninja Framework Benchmarking Test
+
+This is the [Ninja-standalone](http://www.ninjaframework.org/) portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/ninja/json
+
+### Single Query Test
+
+http://localhost:8080/ninja/db
+
+### Multiple Queries Test
+
+http://localhost:8080/ninja/queries/5
+
+### Fortunes Test
+
+http://localhost:8080/ninja/fotunes
+
+### Plaintext Test
+
+http://localhost:8080/ninja/plaintext
+
+

+ 0 - 0
ninja-standalone/__init__.py


+ 28 - 0
ninja-standalone/benchmark_config

@@ -0,0 +1,28 @@
+{
+  "framework": "ninja",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/ninja/json",
+      "db_url": "/ninja/db",
+      "query_url": "/ninja/queries/",
+      "fortune_url": "/ninja/fortunes",
+      "plaintext_url": "/ninja/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "ninja",
+      "language": "Java",
+      "orm": "Full",
+      "platform": "Jetty",
+      "webserver": "Jetty",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ninja-standalone",
+      "notes": "",
+      "versus": "",
+      "skip": "true"
+    }
+  }]
+}

+ 163 - 0
ninja-standalone/pom.xml

@@ -0,0 +1,163 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>helo.world</groupId>
+	<artifactId>hello-ninja-standalone</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<name>Ninja Framework Test Project</name>
+	<description>Nnja test for the TechEmpower/FrameworkBenchmarks project</description>
+
+	<properties>
+		<java-version>1.7</java-version>
+		<ninja.version>2.1.0</ninja.version>
+		<mysql.version>5.1.26</mysql.version>
+		<jetty.version>9.0.5.v20130815</jetty.version>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.ninjaframework</groupId>
+			<artifactId>ninja-servlet</artifactId>
+			<version>${ninja.version}</version>
+		</dependency>
+
+    		<dependency>
+        		<groupId>org.ninjaframework</groupId>
+        		<artifactId>ninja-standalone</artifactId>
+        		<version>${ninja.version}</version>
+    		</dependency>   
+
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+			<version>3.0.1</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.ninjaframework</groupId>
+			<artifactId>ninja-test-utilities</artifactId>
+			<version>${ninja.version}</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>${mysql.version}</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.1</version>
+				<configuration>
+					<source>${java-version}</source>
+					<target>${java-version}</target>
+				</configuration>
+			</plugin>
+			
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <configuration>
+                    <warName>ninja</warName>
+                </configuration>
+            </plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-enforcer-plugin</artifactId>
+				<version>1.0</version>
+				<executions>
+					<execution>
+						<id>enforce-banned-dependencies</id>
+						<goals>
+							<goal>enforce</goal>
+						</goals>
+						<configuration>
+							<rules>
+								<bannedDependencies>
+									<excludes>
+										<exclude>commons-logging</exclude>
+									</excludes>
+								</bannedDependencies>
+							</rules>
+							<fail>true</fail>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.eclipse.jetty</groupId>
+				<artifactId>jetty-maven-plugin</artifactId>
+				<version>${jetty.version}</version>
+				<configuration>
+					<contextPath>/</contextPath>
+					<stopKey>stop</stopKey>
+					<stopPort>8889</stopPort>
+					<scanIntervalSeconds>1</scanIntervalSeconds>
+					<reload>automatic</reload>
+					<scanTargetPatterns>
+						<scanTargetPattern>
+							<directory>target/classes</directory>
+							<includes>
+								<include>**/*</include>
+							</includes>
+							<excludes>
+								<exclude>**/*.ftl.html</exclude>
+								<exclude>assets/**</exclude>
+							</excludes>
+						</scanTargetPattern>
+					</scanTargetPatterns>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-deploy-plugin</artifactId>
+				<version>2.7</version>
+				<configuration>
+					<skip>true</skip>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.4</version>
+				<configuration>
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+					<archive>
+						<manifest>
+							<mainClass>ninja.standalone.NinjaJetty</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+		</plugins>
+
+		<resources>
+			<resource>
+				<directory>src/main/java</directory>
+				<includes>
+					<include>**/*</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</resource>
+			<resource>
+				<directory>src/main/resources</directory>
+				<includes>
+					<include>**/*</include>
+				</includes>
+			</resource>
+		</resources>
+	</build>
+</project>

+ 23 - 0
ninja-standalone/setup.py

@@ -0,0 +1,23 @@
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args, logfile, errfile):
+  setup_util.replace_text("ninja-standalone/src/main/resource/conf/application.conf", "mysql:\/\/.*:3306", "mysql://" + args.database_host + ":3306")
+  
+  try:
+    subprocess.check_call("mvn clean compile assembly:single", shell=True, cwd="ninja-standalone", stderr=errfile, stdout=logfile)
+    subprocess.check_call("java -Dninja.port=8080 -Dninja.mode=prod -Dninja.context=/ninja -jar ninja-standalone/target/hello-ninja-standalone-0.0.1-SNAPSHOT-jar-with-dependencies.jar", shell=True, stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+
+def stop(logfile, errfile):
+  p = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE)
+  out, err = p.communicate()
+  for line in out.splitlines():
+    if 'hello-ninja' in line:
+      pid = int(line.split(None, 2)[1])
+      os.kill(pid, 9)
+  return 0

+ 35 - 0
ninja-standalone/source_code

@@ -0,0 +1,35 @@
+./ninja-standalone/src/
+./ninja-standalone/src/main/
+./ninja-standalone/src/main/java/
+./ninja-standalone/src/main/java/conf
+./ninja-standalone/src/main/java/conf/Routes.java
+./ninja-standalone/src/main/java/conf/application.conf
+./ninja-standalone/src/main/java/conf/messages.properties
+./ninja-standalone/src/main/java/hello/
+./ninja-standalone/src/main/java/hello/controllers/
+./ninja-standalone/src/main/java/hello/controllers/HelloDbController.java
+./ninja-standalone/src/main/java/hello/controllers/HelloFortuneController.java
+./ninja-standalone/src/main/java/hello/controllers/HelloJsonController.java
+./ninja-standalone/src/main/java/hello/controllers/HelloPlaintextController.java
+./ninja-standalone/src/main/java/hello/dao/
+./ninja-standalone/src/main/java/hello/dao/FortuneDao.java
+./ninja-standalone/src/main/java/hello/dao/WorldDao.java
+./ninja-standalone/src/main/java/hello/model/
+./ninja-standalone/src/main/java/hello/model/Fortune.java
+./ninja-standalone/src/main/java/hello/model/World.java
+./ninja-standalone/src/main/java/hello/views/
+./ninja-standalone/src/main/java/hello/views/HelloFortuneController/
+./ninja-standalone/src/main/java/hello/views/HelloFortuneController/index.ftl.html
+./ninja-standalone/src/main/resources/
+./ninja-standalone/src/main/resources/META-INF/
+./ninja-standalone/src/main/resources/META-INF/persistence.xml
+./ninja-standalone/src/main/resources/conf/
+./ninja-standalone/src/main/resources/conf/application.conf
+./ninja-standalone/src/main/resources/conf/messages.properties
+./ninja-standalone/src/main/resources/ehcache.xml
+./ninja-standalone/src/main/resources/logback.xml
+./ninja-standalone/src/main/webapp/
+./ninja-standalone/src/main/webapp/WEB-INF/
+./ninja-standalone/src/main/webapp/WEB-INF/resin-web.xml
+./ninja-standalone/src/main/webapp/WEB-INF/web.xml
+

+ 26 - 0
ninja-standalone/src/main/java/conf/Routes.java

@@ -0,0 +1,26 @@
+package conf;
+
+import hello.controllers.HelloDbController;
+import hello.controllers.HelloFortuneController;
+import hello.controllers.HelloJsonController;
+import hello.controllers.HelloPlaintextController;
+import ninja.Router;
+import ninja.application.ApplicationRoutes;
+
+public class Routes implements ApplicationRoutes {
+
+    @Override
+    public void init(Router router) {
+
+	router.GET().route("/").with(HelloPlaintextController.class, "index");
+	router.GET().route("/plaintext")
+		.with(HelloPlaintextController.class, "index");
+	router.GET().route("/json").with(HelloJsonController.class, "index");
+	router.GET().route("/queries/{queries}")
+		.with(HelloDbController.class, "multiGet");
+	router.GET().route("/db").with(HelloDbController.class, "singleGet");
+	router.GET().route("/fortunes")
+		.with(HelloFortuneController.class, "index");
+
+    }
+}

+ 50 - 0
ninja-standalone/src/main/java/hello/controllers/HelloDbController.java

@@ -0,0 +1,50 @@
+package hello.controllers;
+
+import hello.dao.WorldDao;
+import hello.model.World;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import ninja.Result;
+import ninja.Results;
+import ninja.params.PathParam;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloDbController {
+
+    private static final int DB_ROWS = 10000;
+    private final Random random = ThreadLocalRandom.current();
+
+    @Inject
+    WorldDao worldDao;
+
+    public Result singleGet() {
+	return Results.json().render(getRandomWorld());
+    }
+
+    public Result multiGet(@PathParam("queries") Integer queries) {
+	if (queries == null || queries < 1) {
+	    queries = 1;
+	}
+	if (queries > 500) {
+	    queries = 500;
+	}
+
+	final World[] worlds = new World[queries];
+
+	for (int i = 0; i < queries; i++) {
+	    worlds[i] = getRandomWorld();
+	}
+
+	return Results.json().render(worlds);
+    }
+
+    private World getRandomWorld() {
+	return worldDao.get(random.nextInt(DB_ROWS) + 1);
+    }
+
+}

+ 28 - 0
ninja-standalone/src/main/java/hello/controllers/HelloFortuneController.java

@@ -0,0 +1,28 @@
+package hello.controllers;
+
+import hello.dao.FortuneDao;
+import hello.model.Fortune;
+
+import java.util.Collections;
+import java.util.List;
+
+import ninja.Result;
+import ninja.Results;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloFortuneController {
+
+    @Inject
+    FortuneDao fortuneDao;
+
+    public Result index() {
+	List<Fortune> fortunes = fortuneDao.getAll();
+	fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+	Collections.sort(fortunes);
+
+	return Results.html().render("fortunes", fortunes);
+    }
+}

+ 27 - 0
ninja-standalone/src/main/java/hello/controllers/HelloJsonController.java

@@ -0,0 +1,27 @@
+package hello.controllers;
+
+import ninja.Result;
+import ninja.Results;
+
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloJsonController {
+
+    public Result index() {
+	return Results.json().render(new Message("Hello, world"));
+    }
+
+    public static class Message {
+
+	private final String message;
+
+	public Message(String message) {
+	    this.message = message;
+	}
+
+	public String getMessage() {
+	    return message;
+	}
+    }
+}

+ 13 - 0
ninja-standalone/src/main/java/hello/controllers/HelloPlaintextController.java

@@ -0,0 +1,13 @@
+package hello.controllers;
+
+import ninja.Result;
+import ninja.Results;
+
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloPlaintextController {
+    public Result index() {
+	return Results.html().renderRaw("Hello, world!");
+    }
+}

+ 29 - 0
ninja-standalone/src/main/java/hello/dao/FortuneDao.java

@@ -0,0 +1,29 @@
+package hello.dao;
+
+import hello.model.Fortune;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.persist.Transactional;
+
+public class FortuneDao {
+
+    @Inject
+    Provider<EntityManager> entitiyManagerProvider;
+
+    @Transactional
+    public List<Fortune> getAll() {
+	EntityManager entityManager = entitiyManagerProvider.get();
+
+	Query q = entityManager.createQuery("SELECT x FROM Fortune x");
+	List<Fortune> fortunes = q.getResultList();
+
+	return fortunes;
+    }
+
+}

+ 21 - 0
ninja-standalone/src/main/java/hello/dao/WorldDao.java

@@ -0,0 +1,21 @@
+package hello.dao;
+
+import hello.model.World;
+
+import javax.persistence.EntityManager;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.persist.Transactional;
+
+public class WorldDao {
+
+    @Inject
+    Provider<EntityManager> entitiyManagerProvider;
+
+    @Transactional
+    public World get(int id) {
+	EntityManager entityManager = entitiyManagerProvider.get();
+	return entityManager.find(World.class, id);
+    }
+}

+ 36 - 0
ninja-standalone/src/main/java/hello/model/Fortune.java

@@ -0,0 +1,36 @@
+package hello.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Fortune implements Comparable<Fortune> {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    public int id;
+    public String message;
+
+    public Fortune() {
+
+    }
+
+    public Fortune(int id, String message) {
+	this.id = id;
+	this.message = message;
+    }
+
+    public int getId() {
+	return this.id;
+    }
+
+    public String getMessage() {
+	return this.message;
+    }
+
+    @Override
+    public int compareTo(Fortune other) {
+	return message.compareTo(other.message);
+    }
+}

+ 14 - 0
ninja-standalone/src/main/java/hello/model/World.java

@@ -0,0 +1,14 @@
+package hello.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class World {
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    public int id;
+    public int randomNumber;
+}

+ 20 - 0
ninja-standalone/src/main/java/hello/views/HelloFortuneController/index.ftl.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+	<table>
+		<tr>
+			<th>id</th>
+			<th>message</th>
+		</tr>
+		<#list fortunes as fortune>
+		<tr>
+			<td>${fortune.id}</td>
+			<td>${fortune.message?html}</td>
+		</tr>
+		</#list>
+	</table>
+</body>
+</html>

+ 45 - 0
ninja-standalone/src/main/resources/META-INF/persistence.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+	version="2.0">
+
+	<!-- Direct mysql -->
+	<persistence-unit name="mysql" transaction-type="RESOURCE_LOCAL">
+		<provider>org.hibernate.ejb.HibernatePersistence</provider>
+
+		<properties>
+			<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
+			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
+
+			<property name="hibernate.show_sql" value="false" />
+			<property name="hibernate.format_sql" value="false" />
+
+			<!-- Connection Pooling settings -->
+			<property name="hibernate.connection.provider_class"
+				value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" />
+
+			<property name="hibernate.c3p0.max_size" value="100" />
+			<property name="hibernate.c3p0.min_size" value="0" />
+			<property name="hibernate.c3p0.acquire_increment" value="1" />
+			<property name="hibernate.c3p0.idle_test_period" value="300" />
+			<property name="hibernate.c3p0.max_statements" value="0" />
+			<property name="hibernate.c3p0.timeout" value="100" />
+		</properties>
+	</persistence-unit>
+
+	<!-- Resin datasource -->
+	<persistence-unit name="resin" transaction-type="RESOURCE_LOCAL">
+		<provider>org.hibernate.ejb.HibernatePersistence</provider>
+		<jta-data-source>java:comp/env/jdbc/hello_world</jta-data-source>
+
+		<properties>
+			<property name="hibernate.connection.datasource" value="java:comp/env/jdbc/hello_world" />
+			<property name="hibernate.transaction.factory_class"
+				value="org.hibernate.transaction.JTATransactionFactory" />
+			<property name="hibernate.transaction.manager_lookup_class"
+				value="org.hibernate.transaction.ResinTransactionManagerLookup" />
+		</properties>
+	</persistence-unit>
+</persistence>

+ 38 - 0
ninja-standalone/src/main/resources/conf/application.conf

@@ -0,0 +1,38 @@
+##############################################################################
+# The main properties file to configure your application
+#
+# Properties can be prefixed by "%".
+# "%"" matches a mode you can set as system property. For instance when you
+# are using maven you can do: mvn -Dmode=test jetty:run
+#
+# Using that the following property:
+# %test.myproperty=test property
+# would overwrite the property
+# myproperty=my property
+#
+# You can define as many environments as you want. Simply set them in the mode.
+##############################################################################
+application.name=ninja test application
+
+application.cookie.prefix=NINJA
+
+#ISO Language Code, optionally followed by a valid ISO Country Code. 
+application.languages=en,de
+
+application.session.expire_time_in_seconds=3600
+application.session.send_only_if_changed=true
+application.session.transferred_over_https_only=false
+
+##############################################################################
+# Configure JPA
+# simply tell Ninja which persistence unit to use.
+# The persistence units are defined at META-INF/persistence.xml
+##############################################################################
+ninja.migration.run=false
+
+ninja.jpa.persistence_unit_name = mysql
+db.connection.url=jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&amp;elideSetAutoCommits=true&amp;useLocalSessionState=true&amp;cachePrepStmts=true&amp;cacheCallableStmts=true&amp;alwaysSendSetIsolation=false&amp;prepStmtCacheSize=4096&amp;cacheServerConfiguration=true&amp;prepStmtCacheSqlLimit=2048&amp;zeroDateTimeBehavior=convertToNull&amp;traceProtocol=false&amp;useUnbufferedInput=false&amp;useReadAheadInput=false&amp;maintainTimeStats=false&amp;useServerPrepStmts&amp;cacheRSMetadata=true
+db.connection.username=benchmarkdbuser
+db.connection.password=benchmarkdbpass
+
+application.secret = b9z4AQO0huDRrJXFVjNiNXmSVqPSbcqjEiNjdPVBApb8n9GnxVjWBr9jp8tRfe73

+ 17 - 0
ninja-standalone/src/main/resources/conf/messages.properties

@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2012 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file is utf-8

+ 15 - 0
ninja-standalone/src/main/resources/ehcache.xml

@@ -0,0 +1,15 @@
+<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd" updateCheck="false">
+
+    <defaultCache
+            maxElementsInMemory="10000"
+            eternal="false"
+            timeToIdleSeconds="120"
+            timeToLiveSeconds="120"
+            overflowToDisk="false"
+            maxElementsOnDisk="10000000"
+            diskPersistent="false"
+            diskExpiryThreadIntervalSeconds="120"
+            memoryStoreEvictionPolicy="LRU"
+    /> 
+    
+</ehcache>

+ 14 - 0
ninja-standalone/src/main/resources/logback.xml

@@ -0,0 +1,14 @@
+<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoders are assigned the type
+         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="error">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>

+ 13 - 0
ninja-standalone/src/main/webapp/WEB-INF/resin-web.xml

@@ -0,0 +1,13 @@
+<web-app xmlns="http://caucho.com/ns/resin">
+
+<database jndi-name='jdbc/hello_world'>
+  <driver>
+    <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
+    <url>jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&amp;elideSetAutoCommits=true&amp;useLocalSessionState=true&amp;cachePrepStmts=true&amp;cacheCallableStmts=true&amp;alwaysSendSetIsolation=false&amp;prepStmtCacheSize=4096&amp;cacheServerConfiguration=true&amp;prepStmtCacheSqlLimit=2048&amp;zeroDateTimeBehavior=convertToNull&amp;traceProtocol=false&amp;useUnbufferedInput=false&amp;useReadAheadInput=false&amp;maintainTimeStats=false&amp;useServerPrepStmts&amp;cacheRSMetadata=true</url>
+    <user>benchmarkdbuser</user>
+    <password>benchmarkdbpass</password>
+    <useUnicode/>
+  </driver>
+</database>
+
+</web-app>

+ 32 - 0
ninja-standalone/src/main/webapp/WEB-INF/web.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (C) 2013 the original author or authors.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="true" version="3.0">
+  <display-name>ninja</display-name>
+  <listener>
+    <listener-class>ninja.servlet.NinjaServletListener</listener-class>
+  </listener>
+  <filter>
+    <filter-name>guiceFilter</filter-name>
+    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
+  </filter>
+  <filter-mapping>
+    <filter-name>guiceFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+</web-app>

+ 20 - 0
ninja/.gitignore

@@ -0,0 +1,20 @@
+.DS_Store
+*.pyc
+installs/
+*.log
+*.lock
+node_modules/
+*.war
+target/
+*.out
+*.class
+mods/
+/.settings
+/.buildpath
+/.project
+*.iml
+.idea/
+.hsenv/
+azure.err
+*~
+/.classpath

+ 26 - 0
ninja/README.md

@@ -0,0 +1,26 @@
+# Ninja Framework Benchmarking Test
+
+This is the [Ninja](http://www.ninjaframework.org/) portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+
+## Test URLs
+### JSON Encoding Test
+
+http://localhost:8080/ninja/json
+
+### Single Query Test
+
+http://localhost:8080/ninja/db
+
+### Multiple Queries Test
+
+http://localhost:8080/ninja/queries/5
+
+### Fortunes Test
+
+http://localhost:8080/ninja/fotunes
+
+### Plaintext Test
+
+http://localhost:8080/ninja/plaintext
+
+

+ 0 - 0
ninja/__init__.py


+ 27 - 0
ninja/benchmark_config

@@ -0,0 +1,27 @@
+{
+  "framework": "ninja",
+  "tests": [{
+    "default": {
+      "setup_file": "setup",
+      "json_url": "/ninja/json",
+      "db_url": "/ninja/db",
+      "query_url": "/ninja/queries/",
+      "fortune_url": "/ninja/fortunes",
+      "plaintext_url": "/ninja/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "ninja",
+      "language": "Java",
+      "orm": "Full",
+      "platform": "Servlet",
+      "webserver": "Resin",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ninja",
+      "notes": "",
+      "versus": "servlet"
+    }
+  }]
+}

+ 157 - 0
ninja/pom.xml

@@ -0,0 +1,157 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<groupId>helo.world</groupId>
+	<artifactId>hello-ninja</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<name>Ninja Framework Test Project</name>
+	<description>Nnja test for the TechEmpower/FrameworkBenchmarks project</description>
+
+	<properties>
+		<java-version>1.7</java-version>
+		<ninja.version>2.1.0</ninja.version>
+		<mysql.version>5.1.26</mysql.version>
+		<jetty.version>9.0.5.v20130815</jetty.version>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.ninjaframework</groupId>
+			<artifactId>ninja-servlet</artifactId>
+			<version>${ninja.version}</version>
+		</dependency>
+
+		<dependency>
+			<groupId>javax.servlet</groupId>
+			<artifactId>javax.servlet-api</artifactId>
+			<version>3.0.1</version>
+			<scope>provided</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>org.ninjaframework</groupId>
+			<artifactId>ninja-test-utilities</artifactId>
+			<version>${ninja.version}</version>
+			<scope>test</scope>
+		</dependency>
+
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<version>${mysql.version}</version>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<version>3.1</version>
+				<configuration>
+					<source>${java-version}</source>
+					<target>${java-version}</target>
+				</configuration>
+			</plugin>
+			
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-war-plugin</artifactId>
+                <configuration>
+                    <warName>ninja</warName>
+                </configuration>
+            </plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-enforcer-plugin</artifactId>
+				<version>1.0</version>
+				<executions>
+					<execution>
+						<id>enforce-banned-dependencies</id>
+						<goals>
+							<goal>enforce</goal>
+						</goals>
+						<configuration>
+							<rules>
+								<bannedDependencies>
+									<excludes>
+										<exclude>commons-logging</exclude>
+									</excludes>
+								</bannedDependencies>
+							</rules>
+							<fail>true</fail>
+						</configuration>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.eclipse.jetty</groupId>
+				<artifactId>jetty-maven-plugin</artifactId>
+				<version>${jetty.version}</version>
+				<configuration>
+					<contextPath>/</contextPath>
+					<stopKey>stop</stopKey>
+					<stopPort>8889</stopPort>
+					<scanIntervalSeconds>1</scanIntervalSeconds>
+					<reload>automatic</reload>
+					<scanTargetPatterns>
+						<scanTargetPattern>
+							<directory>target/classes</directory>
+							<includes>
+								<include>**/*</include>
+							</includes>
+							<excludes>
+								<exclude>**/*.ftl.html</exclude>
+								<exclude>assets/**</exclude>
+							</excludes>
+						</scanTargetPattern>
+					</scanTargetPatterns>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-deploy-plugin</artifactId>
+				<version>2.7</version>
+				<configuration>
+					<skip>true</skip>
+				</configuration>
+			</plugin>
+
+			<plugin>
+				<artifactId>maven-assembly-plugin</artifactId>
+				<version>2.4</version>
+				<configuration>
+					<descriptorRefs>
+						<descriptorRef>jar-with-dependencies</descriptorRef>
+					</descriptorRefs>
+					<archive>
+						<manifest>
+							<mainClass>ninja.standalone.NinjaJetty</mainClass>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+		</plugins>
+
+		<resources>
+			<resource>
+				<directory>src/main/java</directory>
+				<includes>
+					<include>**/*</include>
+				</includes>
+				<excludes>
+					<exclude>**/*.java</exclude>
+				</excludes>
+			</resource>
+			<resource>
+				<directory>src/main/resources</directory>
+				<includes>
+					<include>**/*</include>
+				</includes>
+			</resource>
+		</resources>
+	</build>
+</project>

+ 32 - 0
ninja/setup.py

@@ -0,0 +1,32 @@
+import subprocess
+import sys
+import setup_util
+import os
+
+def start(args, logfile, errfile):
+  setup_util.replace_text("ninja/src/main/webapp/WEB-INF/resin-web.xml", "mysql:\/\/.*:3306", "mysql://" + args.database_host + ":3306")
+  
+  try:
+    subprocess.check_call("mvn clean compile war:war", shell=True, cwd="ninja", stderr=errfile, stdout=logfile)
+
+    if os.name == 'nt':
+      subprocess.check_call('rmdir /S /Q "%RESIN_HOME%\\webapps\\"', shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call('mkdir "%RESIN_HOME%\\webapps\\"', shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call('copy ninja\\target\\ninja.war "%RESIN_HOME%\\webapps\\ninja.war"', shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call('"%RESIN_HOME%\\bin\\start.bat -Dninja.mode=prod"', shell=True, stderr=errfile, stdout=logfile)
+    else:
+      subprocess.check_call("rm -rf $RESIN_HOME/webapps/*", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call("cp ninja/target/ninja.war $RESIN_HOME/webapps/ninja.war", shell=True, stderr=errfile, stdout=logfile)
+      subprocess.check_call("$RESIN_HOME/bin/resinctl start -Dninja.mode=prod", shell=True, stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1
+def stop(logfile, errfile):
+  try:
+    if os.name == 'nt':
+      subprocess.check_call('"%RESIN_HOME%\\bin\\stop.bat"', shell=True, stderr=errfile, stdout=logfile)
+    else:
+      subprocess.check_call("$RESIN_HOME/bin/resinctl shutdown", shell=True, stderr=errfile, stdout=logfile)
+    return 0
+  except subprocess.CalledProcessError:
+    return 1

+ 35 - 0
ninja/source_code

@@ -0,0 +1,35 @@
+./ninja/src/
+./ninja/src/main/
+./ninja/src/main/java/
+./ninja/src/main/java/conf
+./ninja/src/main/java/conf/Routes.java
+./ninja/src/main/java/conf/application.conf
+./ninja/src/main/java/conf/messages.properties
+./ninja/src/main/java/hello/
+./ninja/src/main/java/hello/controllers/
+./ninja/src/main/java/hello/controllers/HelloDbController.java
+./ninja/src/main/java/hello/controllers/HelloFortuneController.java
+./ninja/src/main/java/hello/controllers/HelloJsonController.java
+./ninja/src/main/java/hello/controllers/HelloPlaintextController.java
+./ninja/src/main/java/hello/dao/
+./ninja/src/main/java/hello/dao/FortuneDao.java
+./ninja/src/main/java/hello/dao/WorldDao.java
+./ninja/src/main/java/hello/model/
+./ninja/src/main/java/hello/model/Fortune.java
+./ninja/src/main/java/hello/model/World.java
+./ninja/src/main/java/hello/views/
+./ninja/src/main/java/hello/views/HelloFortuneController/
+./ninja/src/main/java/hello/views/HelloFortuneController/index.ftl.html
+./ninja/src/main/resources/
+./ninja/src/main/resources/META-INF/
+./ninja/src/main/resources/META-INF/persistence.xml
+./ninja/src/main/resources/conf/
+./ninja/src/main/resources/conf/application.conf
+./ninja/src/main/resources/conf/messages.properties
+./ninja/src/main/resources/ehcache.xml
+./ninja/src/main/resources/logback.xml
+./ninja/src/main/webapp/
+./ninja/src/main/webapp/WEB-INF/
+./ninja/src/main/webapp/WEB-INF/resin-web.xml
+./ninja/src/main/webapp/WEB-INF/web.xml
+

+ 26 - 0
ninja/src/main/java/conf/Routes.java

@@ -0,0 +1,26 @@
+package conf;
+
+import hello.controllers.HelloDbController;
+import hello.controllers.HelloFortuneController;
+import hello.controllers.HelloJsonController;
+import hello.controllers.HelloPlaintextController;
+import ninja.Router;
+import ninja.application.ApplicationRoutes;
+
+public class Routes implements ApplicationRoutes {
+
+    @Override
+    public void init(Router router) {
+
+	router.GET().route("/").with(HelloPlaintextController.class, "index");
+	router.GET().route("/plaintext")
+		.with(HelloPlaintextController.class, "index");
+	router.GET().route("/json").with(HelloJsonController.class, "index");
+	router.GET().route("/queries/{queries}")
+		.with(HelloDbController.class, "multiGet");
+	router.GET().route("/db").with(HelloDbController.class, "singleGet");
+	router.GET().route("/fortunes")
+		.with(HelloFortuneController.class, "index");
+
+    }
+}

+ 50 - 0
ninja/src/main/java/hello/controllers/HelloDbController.java

@@ -0,0 +1,50 @@
+package hello.controllers;
+
+import hello.dao.WorldDao;
+import hello.model.World;
+
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
+import ninja.Result;
+import ninja.Results;
+import ninja.params.PathParam;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloDbController {
+
+    private static final int DB_ROWS = 10000;
+    private final Random random = ThreadLocalRandom.current();
+
+    @Inject
+    WorldDao worldDao;
+
+    public Result singleGet() {
+	return Results.json().render(getRandomWorld());
+    }
+
+    public Result multiGet(@PathParam("queries") Integer queries) {
+	if (queries == null || queries < 1) {
+	    queries = 1;
+	}
+	if (queries > 500) {
+	    queries = 500;
+	}
+
+	final World[] worlds = new World[queries];
+
+	for (int i = 0; i < queries; i++) {
+	    worlds[i] = getRandomWorld();
+	}
+
+	return Results.json().render(worlds);
+    }
+
+    private World getRandomWorld() {
+	return worldDao.get(random.nextInt(DB_ROWS) + 1);
+    }
+
+}

+ 28 - 0
ninja/src/main/java/hello/controllers/HelloFortuneController.java

@@ -0,0 +1,28 @@
+package hello.controllers;
+
+import hello.dao.FortuneDao;
+import hello.model.Fortune;
+
+import java.util.Collections;
+import java.util.List;
+
+import ninja.Result;
+import ninja.Results;
+
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloFortuneController {
+
+    @Inject
+    FortuneDao fortuneDao;
+
+    public Result index() {
+	List<Fortune> fortunes = fortuneDao.getAll();
+	fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+	Collections.sort(fortunes);
+
+	return Results.html().render("fortunes", fortunes);
+    }
+}

+ 27 - 0
ninja/src/main/java/hello/controllers/HelloJsonController.java

@@ -0,0 +1,27 @@
+package hello.controllers;
+
+import ninja.Result;
+import ninja.Results;
+
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloJsonController {
+
+    public Result index() {
+	return Results.json().render(new Message("Hello, world"));
+    }
+
+    public static class Message {
+
+	private final String message;
+
+	public Message(String message) {
+	    this.message = message;
+	}
+
+	public String getMessage() {
+	    return message;
+	}
+    }
+}

+ 13 - 0
ninja/src/main/java/hello/controllers/HelloPlaintextController.java

@@ -0,0 +1,13 @@
+package hello.controllers;
+
+import ninja.Result;
+import ninja.Results;
+
+import com.google.inject.Singleton;
+
+@Singleton
+public class HelloPlaintextController {
+    public Result index() {
+	return Results.html().renderRaw("Hello, world!");
+    }
+}

+ 29 - 0
ninja/src/main/java/hello/dao/FortuneDao.java

@@ -0,0 +1,29 @@
+package hello.dao;
+
+import hello.model.Fortune;
+
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.Query;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.persist.Transactional;
+
+public class FortuneDao {
+
+    @Inject
+    Provider<EntityManager> entitiyManagerProvider;
+
+    @Transactional
+    public List<Fortune> getAll() {
+	EntityManager entityManager = entitiyManagerProvider.get();
+
+	Query q = entityManager.createQuery("SELECT x FROM Fortune x");
+	List<Fortune> fortunes = q.getResultList();
+
+	return fortunes;
+    }
+
+}

+ 21 - 0
ninja/src/main/java/hello/dao/WorldDao.java

@@ -0,0 +1,21 @@
+package hello.dao;
+
+import hello.model.World;
+
+import javax.persistence.EntityManager;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.persist.Transactional;
+
+public class WorldDao {
+
+    @Inject
+    Provider<EntityManager> entitiyManagerProvider;
+
+    @Transactional
+    public World get(int id) {
+	EntityManager entityManager = entitiyManagerProvider.get();
+	return entityManager.find(World.class, id);
+    }
+}

+ 36 - 0
ninja/src/main/java/hello/model/Fortune.java

@@ -0,0 +1,36 @@
+package hello.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class Fortune implements Comparable<Fortune> {
+    @Id
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    public int id;
+    public String message;
+
+    public Fortune() {
+
+    }
+
+    public Fortune(int id, String message) {
+	this.id = id;
+	this.message = message;
+    }
+
+    public int getId() {
+	return this.id;
+    }
+
+    public String getMessage() {
+	return this.message;
+    }
+
+    @Override
+    public int compareTo(Fortune other) {
+	return message.compareTo(other.message);
+    }
+}

+ 14 - 0
ninja/src/main/java/hello/model/World.java

@@ -0,0 +1,14 @@
+package hello.model;
+
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+
+@Entity
+public class World {
+    @Id
+    @GeneratedValue(strategy = GenerationType.AUTO)
+    public int id;
+    public int randomNumber;
+}

+ 20 - 0
ninja/src/main/java/hello/views/HelloFortuneController/index.ftl.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+	<table>
+		<tr>
+			<th>id</th>
+			<th>message</th>
+		</tr>
+		<#list fortunes as fortune>
+		<tr>
+			<td>${fortune.id}</td>
+			<td>${fortune.message?html}</td>
+		</tr>
+		</#list>
+	</table>
+</body>
+</html>

+ 45 - 0
ninja/src/main/resources/META-INF/persistence.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+	version="2.0">
+
+	<!-- Direct mysql -->
+	<persistence-unit name="mysql" transaction-type="RESOURCE_LOCAL">
+		<provider>org.hibernate.ejb.HibernatePersistence</provider>
+
+		<properties>
+			<property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver" />
+			<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
+
+			<property name="hibernate.show_sql" value="false" />
+			<property name="hibernate.format_sql" value="false" />
+
+			<!-- Connection Pooling settings -->
+			<property name="hibernate.connection.provider_class"
+				value="org.hibernate.service.jdbc.connections.internal.C3P0ConnectionProvider" />
+
+			<property name="hibernate.c3p0.max_size" value="100" />
+			<property name="hibernate.c3p0.min_size" value="0" />
+			<property name="hibernate.c3p0.acquire_increment" value="1" />
+			<property name="hibernate.c3p0.idle_test_period" value="300" />
+			<property name="hibernate.c3p0.max_statements" value="0" />
+			<property name="hibernate.c3p0.timeout" value="100" />
+		</properties>
+	</persistence-unit>
+
+	<!-- Resin datasource -->
+	<persistence-unit name="resin" transaction-type="RESOURCE_LOCAL">
+		<provider>org.hibernate.ejb.HibernatePersistence</provider>
+		<jta-data-source>java:comp/env/jdbc/hello_world</jta-data-source>
+
+		<properties>
+			<property name="hibernate.connection.datasource" value="java:comp/env/jdbc/hello_world" />
+			<property name="hibernate.transaction.factory_class"
+				value="org.hibernate.transaction.JTATransactionFactory" />
+			<property name="hibernate.transaction.manager_lookup_class"
+				value="org.hibernate.transaction.ResinTransactionManagerLookup" />
+		</properties>
+	</persistence-unit>
+</persistence>

+ 40 - 0
ninja/src/main/resources/conf/application.conf

@@ -0,0 +1,40 @@
+##############################################################################
+# The main properties file to configure your application
+#
+# Properties can be prefixed by "%".
+# "%"" matches a mode you can set as system property. For instance when you
+# are using maven you can do: mvn -Dmode=test jetty:run
+#
+# Using that the following property:
+# %test.myproperty=test property
+# would overwrite the property
+# myproperty=my property
+#
+# You can define as many environments as you want. Simply set them in the mode.
+##############################################################################
+application.name=ninja test application
+
+application.cookie.prefix=NINJA
+
+#ISO Language Code, optionally followed by a valid ISO Country Code. 
+application.languages=en,de
+
+application.session.expire_time_in_seconds=3600
+application.session.send_only_if_changed=true
+application.session.transferred_over_https_only=false
+
+##############################################################################
+# Configure JPA
+# simply tell Ninja which persistence unit to use.
+# The persistence units are defined at META-INF/persistence.xml
+##############################################################################
+ninja.migration.run=false
+
+ninja.jpa.persistence_unit_name = resin
+
+%test.ninja.jpa.persistence_unit_name = mysql
+%test.db.connection.url=jdbc:mysql://localhost/hello_world
+%test.db.connection.username=benchmarkdbuser
+%test.db.connection.password=benchmarkdbpass
+
+application.secret = b9z4AQO0huDRrJXFVjNiNXmSVqPSbcqjEiNjdPVBApb8n9GnxVjWBr9jp8tRfe73

+ 17 - 0
ninja/src/main/resources/conf/messages.properties

@@ -0,0 +1,17 @@
+#
+# Copyright (C) 2012 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This file is utf-8

+ 15 - 0
ninja/src/main/resources/ehcache.xml

@@ -0,0 +1,15 @@
+<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd" updateCheck="false">
+
+    <defaultCache
+            maxElementsInMemory="10000"
+            eternal="false"
+            timeToIdleSeconds="120"
+            timeToLiveSeconds="120"
+            overflowToDisk="false"
+            maxElementsOnDisk="10000000"
+            diskPersistent="false"
+            diskExpiryThreadIntervalSeconds="120"
+            memoryStoreEvictionPolicy="LRU"
+    /> 
+    
+</ehcache>

+ 14 - 0
ninja/src/main/resources/logback.xml

@@ -0,0 +1,14 @@
+<configuration>
+
+  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+    <!-- encoders are assigned the type
+         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default -->
+    <encoder>
+      <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <root level="error">
+    <appender-ref ref="STDOUT" />
+  </root>
+</configuration>

+ 13 - 0
ninja/src/main/webapp/WEB-INF/resin-web.xml

@@ -0,0 +1,13 @@
+<web-app xmlns="http://caucho.com/ns/resin">
+
+<database jndi-name='jdbc/hello_world'>
+  <driver>
+    <type>com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource</type>
+    <url>jdbc:mysql://localhost:3306/hello_world?jdbcCompliantTruncation=false&amp;elideSetAutoCommits=true&amp;useLocalSessionState=true&amp;cachePrepStmts=true&amp;cacheCallableStmts=true&amp;alwaysSendSetIsolation=false&amp;prepStmtCacheSize=4096&amp;cacheServerConfiguration=true&amp;prepStmtCacheSqlLimit=2048&amp;zeroDateTimeBehavior=convertToNull&amp;traceProtocol=false&amp;useUnbufferedInput=false&amp;useReadAheadInput=false&amp;maintainTimeStats=false&amp;useServerPrepStmts&amp;cacheRSMetadata=true</url>
+    <user>benchmarkdbuser</user>
+    <password>benchmarkdbpass</password>
+    <useUnicode/>
+  </driver>
+</database>
+
+</web-app>

+ 32 - 0
ninja/src/main/webapp/WEB-INF/web.xml

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Copyright (C) 2013 the original author or authors.
+
+    Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="true" version="3.0">
+  <display-name>ninja</display-name>
+  <listener>
+    <listener-class>ninja.servlet.NinjaServletListener</listener-class>
+  </listener>
+  <filter>
+    <filter-name>guiceFilter</filter-name>
+    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
+  </filter>
+  <filter-mapping>
+    <filter-name>guiceFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+</web-app>

+ 28 - 40
openresty/app.lua

@@ -1,44 +1,32 @@
-local _M = {}
+local mysql = mysql
 
-local cjson = require "cjson"
-local mysql = require "resty.mysql"
-local math = require "math"
-
-local encode = cjson.encode
+local encode = encode
 local random = math.random
-local insert = table.insert
-
-
-function _M.handler(ngx)
-    ngx.header.content_type = 'application/json'
-    
-    if ngx.var.uri == '/json' then
-        local resp = {message = "Hello, World!"}
-        ngx.print( encode(resp) )
-    elseif ngx.var.uri == '/db' then
 
-        local mysqlconn = {
-            host = "DBHOSTNAME",
-            port = 3306,
-            database = "hello_world",
-            user = "benchmarkdbuser",
-            password = "benchmarkdbpass"
-        }
-
-        local db, err = mysql:new()
-        local ok, err = db:connect(mysqlconn)
-        local num_queries = tonumber(ngx.var.arg_queries) or 1
-        local worlds = {}
-        for i=1, num_queries do
-            local wid = random(1, 10000)
-            insert(worlds, db:query('SELECT * FROM World WHERE id = '..wid)[1])
-        end
-        ngx.print( encode(worlds) )
-        local ok, err = db:set_keepalive(0, 256)
-    elseif ngx.var.uri == '/plaintext' then
-        ngx.header.content_type = 'text/plain'
-        ngx.print('Hello, World!')
-    end
+local mysqlconn = {
+	host = "DBHOSTNAME",
+	port = 3306,
+	database = "hello_world",
+	user = "benchmarkdbuser",
+	password = "benchmarkdbpass"
+}
+return function(ngx)
+	local db = mysql:new()
+	assert(db:connect(mysqlconn))
+	local num_queries = tonumber(ngx.var.arg_queries) or 1
+	-- May seem like a stupid branch, but since we know that
+	-- at a benchmark it will always be taken one way,
+	-- it doesn't matter. For me, after a small warmup, the performance
+	-- is identical to a version without the branch
+	-- http://wiki.luajit.org/Numerical-Computing-Performance-Guide
+	if num_queries == 1 then
+		ngx.print(encode(db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]))
+	else
+		local worlds = {}
+		for i=1, num_queries do
+			worlds[#worlds+1] = db:query('SELECT * FROM World WHERE id = '..random(1,10000))[1]
+		end
+		ngx.print( encode(worlds) )
+	end
+	db:set_keepalive(0, 256)
 end
-
-return _M

+ 15 - 4
openresty/nginx.conf

@@ -1,18 +1,29 @@
 #worker_processes  1;
 pid        /tmp/nginx.pid;
-error_log /dev/null crit;
-#error_log /tmp/test.log error;
+error_log stderr error;
+
 events {
     worker_connections  16384;
 }
 
 http {
+    resolver 127.0.0.1;
     access_log off;
-    lua_package_path 'CWD/openresty/?.lua;;';	
+    lua_package_path 'CWD/openresty/?.lua;;';
+    init_by_lua 'encode = require("cjson").encode mysql = require("resty.mysql")';
     server {
         listen       8080;
+        location /plaintext {
+            default_type "text/plain";
+            content_by_lua 'ngx.print("Hello, world!")';
+        }
+
+        location /json {
+            default_type "application/json";
+            content_by_lua 'ngx.print(encode({message = "Hello, World!"}))';
+        }
         location / {
-            content_by_lua 'require("app").handler(ngx)';
+            content_by_lua 'require("app")(ngx)';
         }
     }
 }

+ 1 - 1
rack/Gemfile-jruby

@@ -1,6 +1,6 @@
 source 'http://rubygems.org'
 
-gem 'torqbox', '0.1.2'
+gem 'torqbox', '0.1.4'
 gem 'json', '1.7.6'
 gem "rubyzip", "~> 1.0.0"
 gem "zip-zip", "~> 0.1"

+ 1 - 1
rack/README.md

@@ -13,7 +13,7 @@ The tests were run with:
 * [JRuby 1.7.8](http://jruby.org/)
 * [Rack 1.5.1](http://rack.github.com/)
 * [Unicorn 4.6.2](http://unicorn.bogomips.org/)
-* [TorqBox 0.1.2](http://torquebox.org/torqbox/)
+* [TorqBox 0.1.4](http://torquebox.org/torqbox/)
 
 ## References
 * https://github.com/FooBarWidget/passenger/pull/71

+ 1 - 1
rails-stripped/Gemfile-jruby

@@ -1,7 +1,7 @@
 source 'https://rubygems.org'
 
 gem 'rails', '3.2.13'
-gem 'torqbox', '0.1.2'
+gem 'torqbox', '0.1.4'
 gem 'activerecord-jdbcmysql-adapter', '1.2.6'
 gem "rubyzip", "~> 1.0.0"
 gem "zip-zip", "~> 0.1"

+ 1 - 1
rails-stripped/README.md

@@ -16,7 +16,7 @@ The tests were run with:
 * [JRuby 1.7.8](http://jruby.org/)
 * [Rails 3.2.11](http://rubyonrails.org/)
 * [Unicorn 4.6.2](http://unicorn.bogomips.org/)
-* [TorqBox 0.1.2](http://torquebox.org/torqbox/)
+* [TorqBox 0.1.4](http://torquebox.org/torqbox/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 ## References

+ 1 - 1
rails/Gemfile-jruby

@@ -1,7 +1,7 @@
 source 'https://rubygems.org'
 
 gem 'rails', '3.2.13'
-gem 'torqbox', '0.1.2'
+gem 'torqbox', '0.1.4'
 gem 'activerecord-jdbcmysql-adapter', '1.2.6'
 gem "rubyzip", "~> 1.0.0"
 gem "zip-zip", "~> 0.1"

+ 1 - 1
rails/README.md

@@ -16,7 +16,7 @@ The tests were run with:
 * [JRuby 1.7.8](http://jruby.org/)
 * [Rails 3.2.11](http://rubyonrails.org/)
 * [Unicorn 4.6.2](http://unicorn.bogomips.org/)
-* [TorqBox 0.1.2](http://torquebox.org/torqbox/)
+* [TorqBox 0.1.4](http://torquebox.org/torqbox/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 ## References

+ 2 - 1
revel-jet/benchmark_config

@@ -20,7 +20,8 @@
       "database_os": "Linux",
       "display_name": "revel-jet",
       "notes": "",
-      "versus": "go"
+      "versus": "go",
+      "skip": "true"
     }
   }]
 }

+ 4 - 4
revel-jet/src/benchmark/conf/app.conf

@@ -13,8 +13,8 @@ results.chunked=false
 mode.dev=true
 watch=true
 
-log.trace.output = off
-log.info.output  = off
+log.trace.output = stderr
+log.info.output  = stderr
 log.warn.output  = stderr
 log.error.output = stderr
 
@@ -22,7 +22,7 @@ log.error.output = stderr
 mode.dev=false
 watch=false
 
-log.trace.output = off
-log.info.output  = off
+log.trace.output = stderr
+log.info.output  = stderr
 log.warn.output  = stderr
 log.error.output = stderr

+ 1 - 0
revel-qbs/setup.py

@@ -15,6 +15,7 @@ def start(args, logfile, errfile):
     subprocess.call(r"go build -o bin\revel.exe github.com/robfig/revel/revel", shell=True, cwd=CWD, env=env, stderr=errfile, stdout=logfile)
     subprocess.Popen(r"bin\revel.exe run benchmark prod".rsplit(" "), shell=True, cwd=CWD, env=env, stderr=errfile, stdout=logfile)
     return 0
+  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/revel-qbs')
   subprocess.call("go get -u github.com/robfig/revel/revel github.com/coocood/qbs", shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
   subprocess.call("go build -o bin/revel github.com/robfig/revel/revel", shell=True, cwd=CWD, stderr=errfile, stdout=logfile)
   subprocess.Popen("bin/revel run benchmark prod".rsplit(" "), cwd=CWD, stderr=errfile, stdout=logfile)

+ 3 - 0
revel/setup.py

@@ -4,6 +4,8 @@ import os
 import setup_util
 import time
 
+
+
 def start(args, logfile, errfile):
   setup_util.replace_text("revel/src/benchmark/conf/app.conf", "tcp\(.*:3306\)", "tcp(" + args.database_host + ":3306)")
   if os.name == 'nt':
@@ -13,6 +15,7 @@ def start(args, logfile, errfile):
     subprocess.call(r"go build -o bin\revel.exe github.com/robfig/revel/revel", shell=True, cwd="revel", env=env, stderr=errfile, stdout=logfile)
     subprocess.Popen(r"bin\revel.exe run benchmark prod".rsplit(" "), shell=True, cwd="revel", env=env, stderr=errfile, stdout=logfile)
     return 0
+  os.environ["GOPATH"] = os.path.expanduser('~/FrameworkBenchmarks/revel')
   subprocess.call("go get -u github.com/robfig/revel/revel", shell=True, cwd="revel", stderr=errfile, stdout=logfile)
   subprocess.call("go build -o bin/revel github.com/robfig/revel/revel", shell=True, cwd="revel", stderr=errfile, stdout=logfile)
   subprocess.Popen("bin/revel run benchmark prod".rsplit(" "), cwd="revel", stderr=errfile, stdout=logfile)

+ 4 - 4
revel/src/benchmark/conf/app.conf

@@ -22,7 +22,7 @@ log.error.output = stderr
 mode.dev=false
 watch=false
 
-log.trace.output = off
-log.info.output  = off
-log.warn.output  = off
-log.error.output = %(app.name)s.log
+log.trace.output = stderr
+log.info.output  = stderr
+log.warn.output  = stderr
+log.error.output = stderr

+ 1 - 1
sinatra/Gemfile-jruby

@@ -1,7 +1,7 @@
 source 'https://rubygems.org'
 gem 'sinatra', '1.3.4'
 gem 'sinatra-contrib', '1.3.2'
-gem 'torqbox', '0.1.2'
+gem 'torqbox', '0.1.4'
 gem 'activerecord-jdbcmysql-adapter', '1.2.6'
 gem "sinatra-activerecord", "1.2.2"
 gem "rubyzip", "~> 1.0.0"

+ 1 - 1
sinatra/README.md

@@ -15,7 +15,7 @@ The tests were run with:
 * [JRuby 1.7.8](http://jruby.org/)
 * [Sinatra 1.3.4](http://www.sinatrarb.com/)
 * [Unicorn 4.6.2](http://unicorn.bogomips.org/)
-* [TorqBox 0.1.2](http://torquebox.org/torqbox/)
+* [TorqBox 0.1.4](http://torquebox.org/torqbox/)
 * [MySQL 5.5.29](https://dev.mysql.com/)
 
 ## References

+ 10 - 10
toolset/setup/linux/installer.py

@@ -112,8 +112,8 @@ class Installer:
     # go
     #
 
-    self.__download("http://go.googlecode.com/files/go1.2rc3.linux-amd64.tar.gz");
-    self.__run_command("tar xzf go1.2rc3.linux-amd64.tar.gz")
+    self.__download("http://go.googlecode.com/files/go1.2.linux-amd64.tar.gz");
+    self.__run_command("tar xzf go1.2.linux-amd64.tar.gz")
 
     #
     # Perl
@@ -202,11 +202,11 @@ class Installer:
     # Ur/Web
     #
 
-    self.__download("http://www.impredicative.com/ur/urweb-20130421.tgz")
-    self.__run_command("tar xzf urweb-20130421.tgz")
-    self.__run_command("./configure", cwd="urweb-20130421")
-    self.__run_command("make", cwd="urweb-20130421")
-    self.__run_command("sudo make install", cwd="urweb-20130421")
+    self.__run_command("hg clone http://hg.impredicative.com/urweb/")
+    self.__run_command("./autogen.sh", cwd="urweb")
+    self.__run_command("./configure", cwd="urweb")
+    self.__run_command("make", cwd="urweb")
+    self.__run_command("sudo make install", cwd="urweb")
 
     #######################################
     # Webservers
@@ -290,8 +290,8 @@ class Installer:
     #
     # Vert.x
     #
-    self.__download("http://dl.bintray.com/vertx/downloads/vert.x-2.1M1.tar.gz?direct=true", "vert.x-2.1M1.tar.gz")
-    self.__run_command("tar xzf vert.x-2.1M1.tar.gz")
+    self.__download("http://dl.bintray.com/vertx/downloads/vert.x-2.1M2.tar.gz?direct=true", "vert.x-2.1M2.tar.gz")
+    self.__run_command("tar xzf vert.x-2.1M2.tar.gz")
 
     #
     # Yesod
@@ -347,7 +347,7 @@ class Installer:
 
     easy_install('simplejson==3.3.1', two=True, three=True, pypy=False)
     easy_install('ujson==1.33', three=True)
-    easy_install('https://github.com/surfly/gevent/releases/download/1.0rc3/gevent-1.0rc3.tar.gz', three=False)
+    easy_install('gevent==1.0')
     easy_install('uwsgi', three=True)  # uwsgi is released too often to stick on single version.
 
     # Gunicorn

+ 1 - 1
toolset/setup/windows/installer.ps1

@@ -9,7 +9,7 @@ $python_installer_path    = "2.7.5/$python_installer_file"
 $python_version           = "27"
 $wincache_installer_file  = "wincache-1.3.4-5.4-nts-vc9-x86.exe"
 $wincache_installer_path  = "wincache-1.3.4/$wincache_installer_file"
-$go_installer_file        = "go1.2rc3.windows-amd64.msi"
+$go_installer_file        = "go1.2.windows-amd64.msi"
 $jre_installer_file       = "jre-7u25-windows-x64.exe"
 $jdk_installer_file       = "jdk-7u45-windows-x64.exe"
 $jdk_master_hash          = "943527ed9111cbb746d4ab2bb2c31cd6" 

+ 2 - 3
tornado/server.py

@@ -5,7 +5,7 @@ import json
 import motor
 import tornado.ioloop
 import tornado.web
-from tornado import gen, escape
+from tornado import gen
 import tornado.options
 from tornado.options import options
 import tornado.httpserver
@@ -34,7 +34,6 @@ class PlaintextHandler(BaseHandler):
         self.write(b"Hello, World!")
 
 class QueryTestHandler(BaseHandler):
-    @tornado.web.asynchronous
     @gen.coroutine
     def get(self):
         queries = int(self.get_argument("queries", 0))
@@ -55,7 +54,7 @@ class QueryTestHandler(BaseHandler):
                 worlds.append(world)
             response = json.dumps(worlds)
         self.set_header("Content-Type", "application/json; charset=UTF-8")
-        self.finish(response)
+        self.write(response)
 
 application = tornado.web.Application([
     (r"/json", JsonSerializeTestHandler),

+ 67 - 75
vertx/WebServer.java

@@ -1,25 +1,25 @@
-import java.nio.charset.*;
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.concurrent.ThreadLocalRandom;
 import org.vertx.java.core.Handler;
 import org.vertx.java.core.buffer.Buffer;
 import org.vertx.java.core.eventbus.Message;
 import org.vertx.java.core.http.HttpServerRequest;
 import org.vertx.java.core.http.HttpServerResponse;
-import org.vertx.java.core.json.JsonObject;
 import org.vertx.java.core.json.JsonArray;
+import org.vertx.java.core.json.JsonObject;
 import org.vertx.java.core.json.impl.Json;
 import org.vertx.java.platform.Verticle;
 
-public class WebServer extends Verticle implements Handler<HttpServerRequest> {
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
 
-  private static String helloWorld = "Hello, World!";
-  private static Buffer helloWorldBuffer = new Buffer(helloWorld);
-  private static String helloWorldContentLength = String.valueOf(helloWorldBuffer.length());
-  private static DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
+public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 
+  private Buffer helloWorldBuffer = new Buffer("Hello, World!");
+  private String helloWorldContentLength = String.valueOf(helloWorldBuffer.length());
+  private DateFormat DATE_FORMAT = new SimpleDateFormat("EEE, dd MMM yyyyy HH:mm:ss z");
   private String dateString;
 
   @Override
@@ -34,10 +34,6 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     formatDate();
   }
 
-  private void formatDate() {
-    dateString = DATE_FORMAT.format(new Date());
-  }
-
   @Override
   public void handle(HttpServerRequest req) {
     String path = req.path();
@@ -60,45 +56,40 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     }
   }
 
+  private void formatDate() {
+    dateString = DATE_FORMAT.format(new Date());
+  }
+
   private void handlePlainText(HttpServerRequest req) {
     HttpServerResponse resp = req.response();
-    resp.putHeader("Content-Type", "application/json; charset=UTF-8");
-    resp.putHeader("Content-Length", helloWorldContentLength);
-    resp.putHeader("Server", "vert.x");
-    resp.putHeader("Date", dateString);
+    setHeaders(resp, "text/plain", helloWorldContentLength);
     resp.end(helloWorldBuffer);
   }
 
   private void handleJson(HttpServerRequest req) {
-    String result = Json.encode(Collections.singletonMap("message", "Hello, world!"));
-    sendResponse(req, result);
+    Buffer buff = new Buffer(Json.encode(Collections.singletonMap("message", "Hello, world!")));
+    HttpServerResponse resp = req.response();
+    setHeaders(resp, "application/json", String.valueOf(buff.length()));
+    resp.end(buff);
   }
 
   private void handleDbMongo(final HttpServerRequest req) {
+    findRandom(ThreadLocalRandom.current(), new Handler<Message<JsonObject>>() {
+      @Override
+      public void handle(Message<JsonObject> reply) {
+        JsonObject world = getResultFromReply(reply);
+        String result = world.encode();
+        sendResponse(req, result);
+      }
+    });
+  }
 
-    final Random random = ThreadLocalRandom.current();
-
-    vertx.eventBus().send(
-        "hello.persistor",
-        new JsonObject()
-            .putString("action", "findone")
-            .putString("collection", "World")
-            .putObject("matcher", new JsonObject().putNumber("_id", (random.nextInt(10000) + 1))),
-        new Handler<Message<JsonObject>>() {
-          @Override
-          public void handle(Message<JsonObject> reply) {
-            JsonObject body = reply.body();
-
-            if ("ok".equals(body.getString("status"))) {
-              JsonObject world = body.getObject("result");
-              world.removeField("_id");
-              String result = world.encode();
-              sendResponse(req, result);
-            } else {
-              System.err.println("Failed to execute query");
-            }
-          }
-        });
+  private JsonObject getResultFromReply(Message<JsonObject> reply) {
+    JsonObject body = reply.body();
+    JsonObject world = body.getObject("result");
+    Object id = world.removeField("_id");
+    world.putValue("id", id);
+    return world;
   }
 
   private void handleQueriesMongo(final HttpServerRequest req) {
@@ -108,21 +99,37 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
     } catch (NumberFormatException e) {
       e.printStackTrace();
     }
-
     final MongoHandler dbh = new MongoHandler(req, queriesParam);
     final Random random = ThreadLocalRandom.current();
-
     for (int i = 0; i < queriesParam; i++) {
-      vertx.eventBus().send(
-          "hello.persistor",
-          new JsonObject()
-              .putString("action", "findone")
-              .putString("collection", "World")
-              .putObject("matcher", new JsonObject().putNumber("_id", (random.nextInt(10000) + 1))),
-          dbh);
+      findRandom(random, dbh);
     }
   }
 
+  private void findRandom(Random random, Handler<Message<JsonObject>> handler) {
+    vertx.eventBus().send(
+        "hello.persistor",
+        new JsonObject()
+            .putString("action", "findone")
+            .putString("collection", "World")
+            .putObject("matcher", new JsonObject().putNumber("_id", (random.nextInt(10000) + 1))),
+        handler);
+  }
+
+  private void sendResponse(HttpServerRequest req, String result) {
+    Buffer buff = new Buffer(result);
+    HttpServerResponse resp = req.response();
+    setHeaders(resp, "application/json", String.valueOf(buff.length()));
+    resp.end(buff);
+  }
+
+  private void setHeaders(HttpServerResponse resp, String contentType, String contentLength) {
+    resp.putHeader("Content-Type", contentType);
+    resp.putHeader("Content-Length", contentLength);
+    resp.putHeader("Server", "vert.x");
+    resp.putHeader("Date", dateString);
+  }
+
   private class MongoHandler implements Handler<Message<JsonObject>> {
     private final HttpServerRequest req;
     private final int queries;
@@ -136,30 +143,15 @@ public class WebServer extends Verticle implements Handler<HttpServerRequest> {
 
     @Override
     public void handle(Message<JsonObject> reply) {
-      JsonObject body = reply.body();
-
-      if ("ok".equals(body.getString("status"))) {
-        body.getObject("result").removeField("_id");
-        worlds.add(body.getObject("result"));
-        if (worlds.size() == this.queries) {
-          // All queries have completed; send the response.
-          String result = worlds.encode();
-          sendResponse(req, result);
-        }
-      } else {
-        System.err.println("Failed to execute query");
+      JsonObject world = getResultFromReply(reply);
+      worlds.add(world);
+      if (worlds.size() == this.queries) {
+        // All queries have completed; send the response.
+        String result = worlds.encode();
+        sendResponse(req, result);
       }
     }
   }
-  
-  private void sendResponse(HttpServerRequest req, String result) {
-      int contentLength = result.getBytes(StandardCharsets.UTF_8).length;
-      HttpServerResponse resp = req.response();
-      resp.putHeader("Content-Type", "application/json; charset=UTF-8");
-      resp.putHeader("Content-Length", String.valueOf(contentLength));
-      resp.putHeader("Server", "vert.x");
-      resp.putHeader("Date", dateString);
-      resp.end(result);
-  }
+
 }
 

+ 2 - 2
vertx/app.js

@@ -6,9 +6,9 @@ var persistorConf = {
   host: 'localhost'
 }
 
-container.deployModule('io.vertx~mod-mongo-persistor~2.0.0-final', persistorConf, function (err, dep_id) {
+container.deployModule('io.vertx~mod-mongo-persistor~2.1.1', persistorConf, function (err, dep_id) {
   if (!err) {
-    container.deployVerticle('WebServer.java', 8);
+    container.deployVerticle('WebServer.java', java.lang.Runtime.getRuntime().availableProcessors() * 2);
   } else {
     err.printStackTrace();
   }

+ 1 - 1
webgo/benchmark_config

@@ -20,4 +20,4 @@
       "versus": "go"
     }
   }]
-}
+}