Browse Source

Merge pull request #2282 from knewmanTE/round-14-updated

Update round 14 with latest changes from master
Nate 9 years ago
parent
commit
e08b21a100
100 changed files with 561 additions and 2138 deletions
  1. 7 5
      .github/PULL_REQUEST_TEMPLATE.md
  2. 0 2
      .travis.yml
  3. 67 6
      frameworks/C++/cutelyst/benchmark_config.json
  4. 2 2
      frameworks/C++/cutelyst/nginx.conf
  5. 4 2
      frameworks/C++/cutelyst/setup.sh
  6. 24 0
      frameworks/C++/cutelyst/setup_thread.sh
  7. 1 1
      frameworks/C++/cutelyst/setup_uwsgi_nginx.sh
  8. 12 4
      frameworks/C++/cutelyst/src/cutelyst-benchmarks.cpp
  9. 6 6
      frameworks/C++/cutelyst/src/databaseupdatestest.cpp
  10. 2 2
      frameworks/C++/cutelyst/src/fortunetest.cpp
  11. 4 4
      frameworks/C++/cutelyst/src/multipledatabasequeriestest.cpp
  12. 4 4
      frameworks/C++/cutelyst/src/singledatabasequerytest.cpp
  13. 0 1
      frameworks/C/h2o/CMakeLists.txt
  14. 1 1
      frameworks/C/h2o/setup.sh
  15. 37 61
      frameworks/C/h2o/src/fortune.c
  16. 1 1
      frameworks/C/h2o/src/fortune.h
  17. 35 51
      frameworks/C/h2o/src/request_handler.c
  18. 3 1
      frameworks/C/h2o/src/request_handler.h
  19. 8 2
      frameworks/C/h2o/src/template.c
  20. 5 28
      frameworks/C/h2o/src/world.c
  21. 7 9
      frameworks/Go/falcore/src/framework_benchmarks/falcore.go
  22. 1 1
      frameworks/Go/fasthttp/setup-mysql-prefork.sh
  23. 1 1
      frameworks/Go/fasthttp/setup-mysql.sh
  24. 1 1
      frameworks/Go/fasthttp/setup-postgresql-prefork.sh
  25. 1 1
      frameworks/Go/fasthttp/setup-postgresql.sh
  26. 2 0
      frameworks/Java/jooby/setup.sh
  27. 0 101
      frameworks/Java/sabina/benchmark_config.json
  28. 0 5
      frameworks/Java/sabina/jetty-mongodb.sh
  29. 0 5
      frameworks/Java/sabina/jetty.sh
  30. 0 179
      frameworks/Java/sabina/pom.xml
  31. 0 40
      frameworks/Java/sabina/readme.md
  32. 0 4
      frameworks/Java/sabina/setup.sh
  33. 0 7
      frameworks/Java/sabina/source_code
  34. 0 159
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java
  35. 0 25
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java
  36. 0 19
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Message.java
  37. 0 90
      frameworks/Java/sabina/src/main/java/sabina/benchmark/MongoDbRepository.java
  38. 0 139
      frameworks/Java/sabina/src/main/java/sabina/benchmark/MySqlRepository.java
  39. 0 22
      frameworks/Java/sabina/src/main/java/sabina/benchmark/Repository.java
  40. 0 24
      frameworks/Java/sabina/src/main/java/sabina/benchmark/World.java
  41. 0 20
      frameworks/Java/sabina/src/main/resources/fortunes.mustache
  42. 0 42
      frameworks/Java/sabina/src/main/resources/server.properties
  43. 0 197
      frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java
  44. 0 5
      frameworks/Java/sabina/undertow-mongodb.sh
  45. 0 5
      frameworks/Java/sabina/undertow.sh
  46. 1 0
      frameworks/Java/wicket/setup.sh
  47. 4 4
      frameworks/Java/wildfly-ee7/pom.xml
  48. 2 2
      frameworks/Java/wildfly-ee7/setup.sh
  49. 1 0
      frameworks/JavaScript/nodejs/setup.sh
  50. 0 2
      frameworks/Perl/kelp/benchmark_config.json
  51. 32 29
      frameworks/Python/web2py/README.md
  52. 0 2
      frameworks/Python/web2py/app/app/ABOUT
  53. 0 4
      frameworks/Python/web2py/app/app/LICENSE
  54. 0 76
      frameworks/Python/web2py/app/app/controllers/default.py
  55. 0 41
      frameworks/Python/web2py/app/app/models/db.py
  56. 0 19
      frameworks/Python/web2py/app/app/private/appconfig.ini
  57. 0 38
      frameworks/Python/web2py/app/app/routes.example.py
  58. 0 52
      frameworks/Python/web2py/app/app/views/default/index.html
  59. 0 35
      frameworks/Python/web2py/app/app/views/default/user.html
  60. 0 16
      frameworks/Python/web2py/app/app/views/generic.html
  61. 0 0
      frameworks/Python/web2py/app/optimized/__init__.py
  62. 9 0
      frameworks/Python/web2py/app/optimized/models/app.py
  63. 0 0
      frameworks/Python/web2py/app/optimized/views/__init__.py
  64. 3 5
      frameworks/Python/web2py/app/optimized/views/fortune.html
  65. 6 13
      frameworks/Python/web2py/app/routes.py
  66. 1 0
      frameworks/Python/web2py/app/standard/__init__.py
  67. 15 0
      frameworks/Python/web2py/app/standard/controllers/default.py
  68. 1 0
      frameworks/Python/web2py/app/standard/modules/__init__.py
  69. 51 0
      frameworks/Python/web2py/app/standard/modules/controller.py
  70. 59 0
      frameworks/Python/web2py/app/standard/modules/database.py
  71. 1 0
      frameworks/Python/web2py/app/standard/views/__init__.py
  72. 13 0
      frameworks/Python/web2py/app/standard/views/fortune.html
  73. 15 0
      frameworks/Python/web2py/app/wsgi.py
  74. 35 11
      frameworks/Python/web2py/benchmark_config.json
  75. 12 0
      frameworks/Python/web2py/compile_apps.py
  76. 22 0
      frameworks/Python/web2py/gunicorn_conf.py
  77. 4 1
      frameworks/Python/web2py/requirements.txt
  78. 13 5
      frameworks/Python/web2py/setup.sh
  79. 0 66
      frameworks/Ruby/grape/benchmark_config.json
  80. 0 9
      frameworks/Ruby/grape/run_jruby_puma.sh
  81. 0 9
      frameworks/Ruby/grape/run_torqbox.sh
  82. 0 9
      frameworks/Ruby/grape/run_trinidad.sh
  83. 0 0
      frameworks/Ruby/ngx_mruby/__init__.py
  84. 0 69
      frameworks/Ruby/padrino/benchmark_config.json
  85. 0 7
      frameworks/Ruby/padrino/run_jruby_puma.sh
  86. 0 7
      frameworks/Ruby/padrino/run_torqbox.sh
  87. 0 7
      frameworks/Ruby/padrino/run_trinidad.sh
  88. 0 63
      frameworks/Ruby/rack/benchmark_config.json
  89. 0 9
      frameworks/Ruby/rack/run_jruby_puma.sh
  90. 0 20
      frameworks/Ruby/rails-stripped/benchmark_config.json
  91. 0 69
      frameworks/Ruby/rails/benchmark_config.json
  92. 0 7
      frameworks/Ruby/rails/run_jruby_puma.sh
  93. 0 7
      frameworks/Ruby/rails/run_torqbox.sh
  94. 0 7
      frameworks/Ruby/rails/run_trinidad.sh
  95. 0 23
      frameworks/Ruby/sinatra-sequel/benchmark_config.json
  96. 0 12
      frameworks/Ruby/sinatra-sequel/run_jruby_puma.sh
  97. 0 69
      frameworks/Ruby/sinatra/benchmark_config.json
  98. 0 7
      frameworks/Ruby/sinatra/run_jruby_puma.sh
  99. 2 2
      frameworks/Scala/fintrospect/README.md
  100. 23 20
      frameworks/Scala/fintrospect/benchmark_config.json

+ 7 - 5
.github/PULL_REQUEST_TEMPLATE.md

@@ -1,16 +1,18 @@
+<!--
 ....................................
 ....................................
 
 
-MAKE SURE YOU ARE OPENING A PULL 
+MAKE SURE YOU ARE OPENING A PULL
 REQUEST AGAINST THE CORRECT BRANCH
 REQUEST AGAINST THE CORRECT BRANCH
 
 
 ....................................
 ....................................
 
 
-master = bug fixes directly 
+master = bug fixes directly
 addressing the current preview round
 addressing the current preview round
 
 
-round-X = new features, frameworks, 
-tests, and any other larger changes 
-that you would like to see in the 
+round-X = new features, frameworks,
+tests, and any other larger changes
+that you would like to see in the
 next round
 next round
 
 
 ....................................
 ....................................
+-->

+ 0 - 2
.travis.yml

@@ -98,7 +98,6 @@ env:
     - "TESTDIR=Java/servlet"
     - "TESTDIR=Java/servlet"
     - "TESTDIR=Java/servlet3-cass"
     - "TESTDIR=Java/servlet3-cass"
     - "TESTDIR=Java/spark"
     - "TESTDIR=Java/spark"
-    - "TESTDIR=Java/sabina"
     - "TESTDIR=Java/spring"
     - "TESTDIR=Java/spring"
     - "TESTDIR=Java/tapestry"
     - "TESTDIR=Java/tapestry"
     - "TESTDIR=Java/undertow"
     - "TESTDIR=Java/undertow"
@@ -188,7 +187,6 @@ env:
     - "TESTDIR=Scala/finatra"
     - "TESTDIR=Scala/finatra"
     - "TESTDIR=Scala/fintrospect"
     - "TESTDIR=Scala/fintrospect"
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/lift-stateless"
-    - "TESTDIR=Scala/plain"
     - "TESTDIR=Scala/play2-scala"
     - "TESTDIR=Scala/play2-scala"
     - "TESTDIR=Scala/scalatra"
     - "TESTDIR=Scala/scalatra"
     - "TESTDIR=Scala/scruffy"
     - "TESTDIR=Scala/scruffy"

+ 67 - 6
frameworks/C++/cutelyst/benchmark_config.json

@@ -16,7 +16,7 @@
                 "webserver": "None",
                 "webserver": "None",
                 "os": "Linux",
                 "os": "Linux",
                 "database_os": "Linux",
                 "database_os": "Linux",
-                "display_name": "cutelyst-uwsgi",
+                "display_name": "cutelyst-pf",
                 "notes": "",
                 "notes": "",
                 "versus": ""
                 "versus": ""
             },
             },
@@ -37,7 +37,7 @@
                 "webserver": "None",
                 "webserver": "None",
                 "os": "Linux",
                 "os": "Linux",
                 "database_os": "Linux",
                 "database_os": "Linux",
-                "display_name": "cutelyst-uwsgi-pg-raw",
+                "display_name": "cutelyst-pf-pg-raw",
                 "notes": "",
                 "notes": "",
                 "versus": ""
                 "versus": ""
             },
             },
@@ -58,7 +58,68 @@
                 "webserver": "None",
                 "webserver": "None",
                 "os": "Linux",
                 "os": "Linux",
                 "database_os": "Linux",
                 "database_os": "Linux",
-                "display_name": "cutelyst-uwsgi-mysql-raw",
+                "display_name": "cutelyst-pf-mysql-raw",
+                "notes": "",
+                "versus": ""
+            },
+            "thread": {
+                "setup_file": "setup_thread",
+                "json_url": "/json",
+                "plaintext_url": "/plaintext",
+                "port": 8080,
+                "approach": "Realistic",
+                "classification": "Fullstack",
+                "database": "None",
+                "framework": "cutelyst",
+                "language": "C++",
+                "orm": "Raw",
+                "platform": "Qt",
+                "webserver": "None",
+                "os": "Linux",
+                "database_os": "Linux",
+                "display_name": "cutelyst-thread",
+                "notes": "",
+                "versus": ""
+            },
+            "thread-postgres-raw": {
+                "setup_file": "setup_thread",
+                "db_url": "/db_postgres",
+                "query_url": "/query_postgres?queries=",
+                "update_url": "/updates_postgres?queries=",
+                "fortune_url": "/fortunes_raw_postgres",
+                "port": 8080,
+                "approach": "Realistic",
+                "classification": "Platform",
+                "database": "Postgres",
+                "framework": "cutelyst",
+                "language": "C++",
+                "orm": "Raw",
+                "platform": "Qt",
+                "webserver": "None",
+                "os": "Linux",
+                "database_os": "Linux",
+                "display_name": "cutelyst-thread-pg-raw",
+                "notes": "",
+                "versus": ""
+            },
+            "thread-mysql-raw": {
+                "setup_file": "setup_thread",
+                "db_url": "/db_mysql",
+                "query_url": "/query_mysql?queries=",
+                "update_url": "/updates_mysql?queries=",
+                "fortune_url": "/fortunes_raw_mysql",
+                "port": 8080,
+                "approach": "Realistic",
+                "classification": "Platform",
+                "database": "MySQL",
+                "framework": "cutelyst",
+                "language": "C++",
+                "orm": "Raw",
+                "platform": "Qt",
+                "webserver": "None",
+                "os": "Linux",
+                "database_os": "Linux",
+                "display_name": "cutelyst-thread-mysql-raw",
                 "notes": "",
                 "notes": "",
                 "versus": ""
                 "versus": ""
             },
             },
@@ -74,7 +135,7 @@
                 "language": "C++",
                 "language": "C++",
                 "orm": "Raw",
                 "orm": "Raw",
                 "platform": "Qt",
                 "platform": "Qt",
-                "webserver": "None",
+                "webserver": "nginx",
                 "os": "Linux",
                 "os": "Linux",
                 "database_os": "Linux",
                 "database_os": "Linux",
                 "display_name": "cutelyst-uwsgi-nginx",
                 "display_name": "cutelyst-uwsgi-nginx",
@@ -95,7 +156,7 @@
                 "language": "C++",
                 "language": "C++",
                 "orm": "Raw",
                 "orm": "Raw",
                 "platform": "Qt",
                 "platform": "Qt",
-                "webserver": "None",
+                "webserver": "nginx",
                 "os": "Linux",
                 "os": "Linux",
                 "database_os": "Linux",
                 "database_os": "Linux",
                 "display_name": "cutelyst-uwsgi-nginx-pg-raw",
                 "display_name": "cutelyst-uwsgi-nginx-pg-raw",
@@ -116,7 +177,7 @@
                 "language": "C++",
                 "language": "C++",
                 "orm": "Raw",
                 "orm": "Raw",
                 "platform": "Qt",
                 "platform": "Qt",
-                "webserver": "None",
+                "webserver": "nginx",
                 "os": "Linux",
                 "os": "Linux",
                 "database_os": "Linux",
                 "database_os": "Linux",
                 "display_name": "cutelyst-uwsgi-nginx-mysql-raw",
                 "display_name": "cutelyst-uwsgi-nginx-mysql-raw",

+ 2 - 2
frameworks/C++/cutelyst/nginx.conf

@@ -1,6 +1,6 @@
 # This file is based on /usr/local/nginx/conf/nginx.conf.default.
 # This file is based on /usr/local/nginx/conf/nginx.conf.default.
 
 
-# One worker process per core
+worker_processes auto;
 error_log stderr error;
 error_log stderr error;
 
 
 events {
 events {
@@ -27,7 +27,7 @@ http {
     # some worker processes to be handling too connections relative to the
     # some worker processes to be handling too connections relative to the
     # other workers based on an initial imbalance, so this is disabled for
     # other workers based on an initial imbalance, so this is disabled for
     # now.
     # now.
-#    keepalive_requests 1000;
+    keepalive_requests 1000;
 
 
     #keepalive_timeout  0;
     #keepalive_timeout  0;
     keepalive_timeout  65;
     keepalive_timeout  65;

+ 4 - 2
frameworks/C++/cutelyst/setup.sh

@@ -3,7 +3,7 @@
 fw_depends cutelyst
 fw_depends cutelyst
 
 
 sed -i 's|DatabaseHostName=.*|DatabaseHostName='"$DBHOST"'|g' config/config.ini
 sed -i 's|DatabaseHostName=.*|DatabaseHostName='"$DBHOST"'|g' config/config.ini
-sed -i 's|SendDate=.*|SendDate=true|g' config/config.ini
+sed -i 's|SendDate=.*|SendDate=false|g' config/config.ini
 
 
 cd $IROOT
 cd $IROOT
 mkdir cutelyst-benchmarks || true
 mkdir cutelyst-benchmarks || true
@@ -19,4 +19,6 @@ make clean
 make -j $MAX_THREADS
 make -j $MAX_THREADS
 
 
 export LD_LIBRARY_PATH=/opt/qt${QT_VERSION_MM}/lib:${IROOT}/lib/x86_64-linux-gnu/
 export LD_LIBRARY_PATH=/opt/qt${QT_VERSION_MM}/lib:${IROOT}/lib/x86_64-linux-gnu/
-uwsgi --ini ${TROOT}/config/config.ini --cutelyst-app ${IROOT}/cutelyst-benchmarks/src/libcutelyst_benchmarks.so -p $(( $MAX_THREADS * 2 )) &
+export CUTELYST_CONFIG=${TROOT}/config/config.ini
+
+${IROOT}/bin/cutelyst-wsgi --http-socket :8080 -a ${IROOT}/cutelyst-benchmarks/src/libcutelyst_benchmarks.so -p $MAX_THREADS &

+ 24 - 0
frameworks/C++/cutelyst/setup_thread.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+fw_depends cutelyst
+
+sed -i 's|DatabaseHostName=.*|DatabaseHostName='"$DBHOST"'|g' config/config.ini
+sed -i 's|SendDate=.*|SendDate=false|g' config/config.ini
+
+cd $IROOT
+mkdir cutelyst-benchmarks || true
+cd cutelyst-benchmarks
+rm -rf *
+
+QT_VERSION_MM=56
+export CMAKE_PREFIX_PATH=/opt/qt${QT_VERSION_MM}:${IROOT}
+
+cmake $TROOT -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$IROOT
+
+make clean
+make -j $MAX_THREADS
+
+export LD_LIBRARY_PATH=/opt/qt${QT_VERSION_MM}/lib:${IROOT}/lib/x86_64-linux-gnu/
+export CUTELYST_CONFIG=${TROOT}/config/config.ini
+
+${IROOT}/bin/cutelyst-wsgi --http-socket :8080 -a ${IROOT}/cutelyst-benchmarks/src/libcutelyst_benchmarks.so -t $MAX_THREADS &

+ 1 - 1
frameworks/C++/cutelyst/setup_uwsgi_nginx.sh

@@ -22,4 +22,4 @@ make -j $MAX_THREADS
 nginx -c $TROOT/nginx.conf
 nginx -c $TROOT/nginx.conf
 
 
 export LD_LIBRARY_PATH=/opt/qt${QT_VERSION_MM}/lib:${IROOT}/lib/x86_64-linux-gnu/
 export LD_LIBRARY_PATH=/opt/qt${QT_VERSION_MM}/lib:${IROOT}/lib/x86_64-linux-gnu/
-uwsgi --ini ${TROOT}/config/config_socket.ini --cutelyst-app ${IROOT}/cutelyst-benchmarks/src/libcutelyst_benchmarks.so -p $(( $MAX_THREADS * 2 )) &
+uwsgi --ini ${TROOT}/config/config_socket.ini --cutelyst-app ${IROOT}/cutelyst-benchmarks/src/libcutelyst_benchmarks.so -p $MAX_THREADS &

+ 12 - 4
frameworks/C++/cutelyst/src/cutelyst-benchmarks.cpp

@@ -4,7 +4,10 @@
 
 
 #include <QtSql/QSqlDatabase>
 #include <QtSql/QSqlDatabase>
 #include <QtSql/QSqlError>
 #include <QtSql/QSqlError>
+#include <QCoreApplication>
+#include <QThread>
 #include <QDebug>
 #include <QDebug>
+#include <QMutexLocker>
 
 
 #include "root.h"
 #include "root.h"
 #include "jsontest.h"
 #include "jsontest.h"
@@ -16,6 +19,8 @@
 
 
 using namespace Cutelyst;
 using namespace Cutelyst;
 
 
+static QMutex mutex;
+
 cutelyst_benchmarks::cutelyst_benchmarks(QObject *parent) : Application(parent)
 cutelyst_benchmarks::cutelyst_benchmarks(QObject *parent) : Application(parent)
 {
 {
 }
 }
@@ -46,27 +51,30 @@ bool cutelyst_benchmarks::init()
 
 
 bool cutelyst_benchmarks::postFork()
 bool cutelyst_benchmarks::postFork()
 {
 {
+    QMutexLocker locker(&mutex);
+
     QSqlDatabase db;
     QSqlDatabase db;
-    db = QSqlDatabase::addDatabase(QLatin1String("QPSQL"), QLatin1String("postgres"));
+    db = QSqlDatabase::addDatabase(QLatin1String("QPSQL"), QLatin1String("postgres-") + QThread::currentThread()->objectName());
     db.setDatabaseName(QLatin1String("hello_world"));
     db.setDatabaseName(QLatin1String("hello_world"));
     db.setUserName(QLatin1String("benchmarkdbuser"));
     db.setUserName(QLatin1String("benchmarkdbuser"));
     db.setPassword(QLatin1String("benchmarkdbpass"));
     db.setPassword(QLatin1String("benchmarkdbpass"));
     db.setHostName(config(QLatin1String("DatabaseHostName")).toString());
     db.setHostName(config(QLatin1String("DatabaseHostName")).toString());
     if (!db.open()) {
     if (!db.open()) {
-        qDebug() << "Error opening db:" << db << db.lastError().databaseText();
+        qDebug() << "Error opening PostgreSQL db:" << db << db.connectionName() << db.lastError().databaseText();
         return false;
         return false;
     }
     }
 
 
-    db = QSqlDatabase::addDatabase(QLatin1String("QMYSQL"), QLatin1String("mysql"));
+    db = QSqlDatabase::addDatabase(QLatin1String("QMYSQL"), QLatin1String("mysql-") + QThread::currentThread()->objectName());
     db.setDatabaseName(QLatin1String("hello_world"));
     db.setDatabaseName(QLatin1String("hello_world"));
     db.setUserName(QLatin1String("benchmarkdbuser"));
     db.setUserName(QLatin1String("benchmarkdbuser"));
     db.setPassword(QLatin1String("benchmarkdbpass"));
     db.setPassword(QLatin1String("benchmarkdbpass"));
     db.setHostName(config(QLatin1String("DatabaseHostName")).toString());
     db.setHostName(config(QLatin1String("DatabaseHostName")).toString());
     if (!db.open()) {
     if (!db.open()) {
-        qDebug() << "Error opening db:" << db << db.lastError().databaseText();
+        qDebug() << "Error opening MySQL db:" << db << db.connectionName() << db.lastError().databaseText();
         return false;
         return false;
     }
     }
 
 
+    qDebug() << "Connections" << QCoreApplication::applicationPid() << QThread::currentThread() << QSqlDatabase::connectionNames();
 //    db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("sqlite"));
 //    db = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), QLatin1String("sqlite"));
 //    if (!db.open()) {
 //    if (!db.open()) {
 //        qDebug() << "Error opening db:" << db << db.lastError().databaseText();
 //        qDebug() << "Error opening db:" << db << db.lastError().databaseText();

+ 6 - 6
frameworks/C++/cutelyst/src/databaseupdatestest.cpp

@@ -18,10 +18,10 @@ void DatabaseUpdatesTest::updates_postgres(Context *c)
 {
 {
     QSqlQuery query = CPreparedSqlQueryForDatabase(
     QSqlQuery query = CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT randomNumber FROM world WHERE id = :id"),
                 QLatin1String("SELECT randomNumber FROM world WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("postgres")));
+                QSqlDatabase::database(QLatin1String("postgres-") + QThread::currentThread()->objectName()));
     QSqlQuery updateQuery = CPreparedSqlQueryForDatabase(
     QSqlQuery updateQuery = CPreparedSqlQueryForDatabase(
                 QLatin1String("UPDATE world SET randomNumber = :randomNumber WHERE id = :id"),
                 QLatin1String("UPDATE world SET randomNumber = :randomNumber WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("postgres")));
+                QSqlDatabase::database(QLatin1String("postgres-") + QThread::currentThread()->objectName()));
     processQuery(c, query, updateQuery);
     processQuery(c, query, updateQuery);
 }
 }
 
 
@@ -29,10 +29,10 @@ void DatabaseUpdatesTest::updates_mysql(Context *c)
 {
 {
     QSqlQuery query = CPreparedSqlQueryForDatabase(
     QSqlQuery query = CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT randomNumber FROM world WHERE id = :id"),
                 QLatin1String("SELECT randomNumber FROM world WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("mysql")));
+                QSqlDatabase::database(QLatin1String("mysql-") + QThread::currentThread()->objectName()));
     QSqlQuery updateQuery = CPreparedSqlQueryForDatabase(
     QSqlQuery updateQuery = CPreparedSqlQueryForDatabase(
                 QLatin1String("UPDATE world SET randomNumber = :randomNumber WHERE id = :id"),
                 QLatin1String("UPDATE world SET randomNumber = :randomNumber WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("mysql")));
+                QSqlDatabase::database(QLatin1String("mysql-") + QThread::currentThread()->objectName()));
     processQuery(c, query, updateQuery);
     processQuery(c, query, updateQuery);
 }
 }
 
 
@@ -48,7 +48,7 @@ void DatabaseUpdatesTest::processQuery(Context *c, QSqlQuery &query, QSqlQuery &
     }
     }
 
 
     for (int i = 0; i < queries; ++i) {
     for (int i = 0; i < queries; ++i) {
-        int id = (qrand() % 9999) + 1;
+        int id = (qrand() % 10000) + 1;
 
 
         query.bindValue(QStringLiteral(":id"), id);
         query.bindValue(QStringLiteral(":id"), id);
         if (!query.exec() || !query.next()) {
         if (!query.exec() || !query.next()) {
@@ -56,7 +56,7 @@ void DatabaseUpdatesTest::processQuery(Context *c, QSqlQuery &query, QSqlQuery &
             return;
             return;
         }
         }
 
 
-        int randomNumber = (qrand() % 9999) + 1;
+        int randomNumber = (qrand() % 10000) + 1;
         updateQuery.bindValue(QStringLiteral(":id"), id);
         updateQuery.bindValue(QStringLiteral(":id"), id);
         updateQuery.bindValue(QStringLiteral(":randomNumber"), randomNumber);
         updateQuery.bindValue(QStringLiteral(":randomNumber"), randomNumber);
         if (!updateQuery.exec()) {
         if (!updateQuery.exec()) {

+ 2 - 2
frameworks/C++/cutelyst/src/fortunetest.cpp

@@ -34,14 +34,14 @@ QSqlQuery FortuneTest::postgresQuery()
 {
 {
     return CPreparedSqlQueryForDatabase(
     return CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT id, message FROM fortune"),
                 QLatin1String("SELECT id, message FROM fortune"),
-                QSqlDatabase::database(QLatin1String("postgres")));
+                QSqlDatabase::database(QLatin1String("postgres-") + QThread::currentThread()->objectName()));
 }
 }
 
 
 QSqlQuery FortuneTest::mysqlQuery()
 QSqlQuery FortuneTest::mysqlQuery()
 {
 {
     return CPreparedSqlQueryForDatabase(
     return CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT id, message FROM fortune"),
                 QLatin1String("SELECT id, message FROM fortune"),
-                QSqlDatabase::database(QLatin1String("mysql")));
+                QSqlDatabase::database(QLatin1String("mysql-") + QThread::currentThread()->objectName()));
 }
 }
 
 
 static bool caseSensitiveLessThan(const Fortune &a1, const Fortune &a2)
 static bool caseSensitiveLessThan(const Fortune &a1, const Fortune &a2)

+ 4 - 4
frameworks/C++/cutelyst/src/multipledatabasequeriestest.cpp

@@ -18,7 +18,7 @@ void MultipleDatabaseQueriesTest::query_postgres(Context *c)
 {
 {
     QSqlQuery query = CPreparedSqlQueryForDatabase(
     QSqlQuery query = CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("postgres")));
+                QSqlDatabase::database(QLatin1String("postgres-") + QThread::currentThread()->objectName()));
     processQuery(c, query);
     processQuery(c, query);
 }
 }
 
 
@@ -26,7 +26,7 @@ void MultipleDatabaseQueriesTest::query_mysql(Context *c)
 {
 {
     QSqlQuery query = CPreparedSqlQueryForDatabase(
     QSqlQuery query = CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("mysql")));
+                QSqlDatabase::database(QLatin1String("mysql-") + QThread::currentThread()->objectName()));
     processQuery(c, query);
     processQuery(c, query);
 }
 }
 
 
@@ -42,9 +42,9 @@ void MultipleDatabaseQueriesTest::processQuery(Context *c, QSqlQuery &query)
     }
     }
 
 
     for (int i = 0; i < queries; ++i) {
     for (int i = 0; i < queries; ++i) {
-        int id = qrand() % 9999;
+        int id = (qrand() % 10000) + 1;
 
 
-        query.bindValue(QStringLiteral(":id"), id + 1);
+        query.bindValue(QStringLiteral(":id"), id);
         if (!query.exec() || !query.next()) {
         if (!query.exec() || !query.next()) {
             c->res()->setStatus(Response::InternalServerError);
             c->res()->setStatus(Response::InternalServerError);
             return;
             return;

+ 4 - 4
frameworks/C++/cutelyst/src/singledatabasequerytest.cpp

@@ -17,7 +17,7 @@ void SingleDatabaseQueryTest::db_postgres(Context *c)
 {
 {
     QSqlQuery query = CPreparedSqlQueryForDatabase(
     QSqlQuery query = CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("postgres")));
+                QSqlDatabase::database(QLatin1String("postgres-") + QThread::currentThread()->objectName()));
     processQuery(c, query);
     processQuery(c, query);
 }
 }
 
 
@@ -25,15 +25,15 @@ void SingleDatabaseQueryTest::db_mysql(Context *c)
 {
 {
     QSqlQuery query = CPreparedSqlQueryForDatabase(
     QSqlQuery query = CPreparedSqlQueryForDatabase(
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
                 QLatin1String("SELECT id, randomNumber FROM world WHERE id = :id"),
-                QSqlDatabase::database(QLatin1String("mysql")));
+                QSqlDatabase::database(QLatin1String("mysql-") + QThread::currentThread()->objectName()));
     processQuery(c, query);
     processQuery(c, query);
 }
 }
 
 
 void SingleDatabaseQueryTest::processQuery(Context *c, QSqlQuery &query)
 void SingleDatabaseQueryTest::processQuery(Context *c, QSqlQuery &query)
 {
 {
-    int id = qrand() % 9999;
+    int id = (qrand() % 10000) + 1;
 
 
-    query.bindValue(QStringLiteral(":id"), id + 1);
+    query.bindValue(QStringLiteral(":id"), id);
     if (!query.exec() || !query.next()) {
     if (!query.exec() || !query.next()) {
         c->res()->setStatus(Response::InternalServerError);
         c->res()->setStatus(Response::InternalServerError);
         return;
         return;

+ 0 - 1
frameworks/C/h2o/CMakeLists.txt

@@ -8,7 +8,6 @@ find_path(MUSTACHE_C_INCLUDE mustache.h)
 find_path(YAJL_INCLUDE yajl/yajl_gen.h)
 find_path(YAJL_INCLUDE yajl/yajl_gen.h)
 set(COMMON_OPTIONS -flto -pthread)
 set(COMMON_OPTIONS -flto -pthread)
 add_compile_options(-std=gnu11 -pedantic -Wall -Wextra ${COMMON_OPTIONS})
 add_compile_options(-std=gnu11 -pedantic -Wall -Wextra ${COMMON_OPTIONS})
-set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fsanitize=address")
 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fstack-protector-all -D_FORTIFY_SOURCE=2")
 set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fstack-protector-all -D_FORTIFY_SOURCE=2")
 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast")
 set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -Ofast")
 set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -Ofast")
 set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -Ofast")

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

@@ -25,7 +25,7 @@ run_curl()
 
 
 run_h2o_app()
 run_h2o_app()
 {
 {
-	"$1/h2o_app" -a2 -f "$2/template/fortunes.mustache" -m2 "$3" "$4" \
+	"$1/h2o_app" -a2 -f "$2/template/fortunes.mustache" -m8 "$3" "$4" \
 		-d "host=$DBHOST dbname=hello_world user=benchmarkdbuser password=benchmarkdbpass" &
 		-d "host=$DBHOST dbname=hello_world user=benchmarkdbuser password=benchmarkdbpass" &
 }
 }
 
 

+ 37 - 61
frameworks/C/h2o/src/fortune.c

@@ -49,6 +49,7 @@ typedef struct {
 	iovec_list_t *iovec_list_iter;
 	iovec_list_t *iovec_list_iter;
 	h2o_req_t *req;
 	h2o_req_t *req;
 	list_t *result;
 	list_t *result;
+	size_t content_length;
 	size_t num_result;
 	size_t num_result;
 	db_query_param_t param;
 	db_query_param_t param;
 	h2o_generator_t generator;
 	h2o_generator_t generator;
@@ -56,9 +57,8 @@ typedef struct {
 
 
 static uintmax_t add_iovec(mustache_api_t *api,
 static uintmax_t add_iovec(mustache_api_t *api,
                            void *userdata,
                            void *userdata,
-                           char *buffer,
+                           const char *buffer,
                            uintmax_t buffer_size);
                            uintmax_t buffer_size);
-static void cleanup_fortunes(struct st_h2o_generator_t *self, h2o_req_t *req);
 static int compare_fortunes(const list_t *x, const list_t *y);
 static int compare_fortunes(const list_t *x, const list_t *y);
 static void complete_fortunes(struct st_h2o_generator_t *self, h2o_req_t *req);
 static void complete_fortunes(struct st_h2o_generator_t *self, h2o_req_t *req);
 static list_t *get_sorted_sublist(list_t *head);
 static list_t *get_sorted_sublist(list_t *head);
@@ -76,7 +76,7 @@ static list_t *sort_fortunes(list_t *head);
 
 
 static uintmax_t add_iovec(mustache_api_t *api,
 static uintmax_t add_iovec(mustache_api_t *api,
                            void *userdata,
                            void *userdata,
-                           char *buffer,
+                           const char *buffer,
                            uintmax_t buffer_size)
                            uintmax_t buffer_size)
 {
 {
 	IGNORE_FUNCTION_PARAMETER(api);
 	IGNORE_FUNCTION_PARAMETER(api);
@@ -101,33 +101,14 @@ static uintmax_t add_iovec(mustache_api_t *api,
 	}
 	}
 
 
 	if (ret) {
 	if (ret) {
-		iovec_list->iov[iovec_list->iovcnt].base = buffer;
+		iovec_list->iov[iovec_list->iovcnt].base = (char *) buffer;
 		iovec_list->iov[iovec_list->iovcnt++].len = buffer_size;
 		iovec_list->iov[iovec_list->iovcnt++].len = buffer_size;
+		fortune_ctx->content_length += buffer_size;
 	}
 	}
 
 
 	return ret;
 	return ret;
 }
 }
 
 
-static void cleanup_fortunes(struct st_h2o_generator_t *self, h2o_req_t *req)
-{
-	IGNORE_FUNCTION_PARAMETER(req);
-
-	fortune_ctx_t * const fortune_ctx = H2O_STRUCT_FROM_MEMBER(fortune_ctx_t,
-	                                                           generator,
-	                                                           self);
-	const list_t *iter = fortune_ctx->result;
-
-	if (iter)
-		do {
-			const fortune_t * const fortune = H2O_STRUCT_FROM_MEMBER(fortune_t, l, iter);
-
-			if (fortune->data)
-				PQclear(fortune->data);
-
-			iter = iter->next;
-		} while (iter);
-}
-
 static int compare_fortunes(const list_t *x, const list_t *y)
 static int compare_fortunes(const list_t *x, const list_t *y)
 {
 {
 	const fortune_t * const f1 = H2O_STRUCT_FROM_MEMBER(fortune_t, l, x);
 	const fortune_t * const f1 = H2O_STRUCT_FROM_MEMBER(fortune_t, l, x);
@@ -146,19 +127,12 @@ static void complete_fortunes(struct st_h2o_generator_t *self, h2o_req_t *req)
 	fortune_ctx_t * const fortune_ctx = H2O_STRUCT_FROM_MEMBER(fortune_ctx_t,
 	fortune_ctx_t * const fortune_ctx = H2O_STRUCT_FROM_MEMBER(fortune_ctx_t,
 	                                                           generator,
 	                                                           generator,
 	                                                           self);
 	                                                           self);
+	iovec_list_t * const iovec_list = H2O_STRUCT_FROM_MEMBER(iovec_list_t,
+	                                                         l,
+	                                                         fortune_ctx->iovec_list);
 
 
-	if (fortune_ctx->iovec_list) {
-		iovec_list_t * const iovec_list = H2O_STRUCT_FROM_MEMBER(iovec_list_t,
-		                                                         l,
-		                                                         fortune_ctx->iovec_list);
-
-		fortune_ctx->iovec_list = iovec_list->l.next;
-		h2o_send(fortune_ctx->req, iovec_list->iov, iovec_list->iovcnt, false);
-	}
-	else {
-		h2o_send(req, NULL, 0, true);
-		cleanup_fortunes(self, req);
-	}
+	fortune_ctx->iovec_list = iovec_list->l.next;
+	h2o_send(req, iovec_list->iov, iovec_list->iovcnt, !fortune_ctx->iovec_list);
 }
 }
 
 
 static list_t *get_sorted_sublist(list_t *head)
 static list_t *get_sorted_sublist(list_t *head)
@@ -218,7 +192,6 @@ static void on_fortune_error(db_query_param_t *param, const char *error_string)
 	                                                           param,
 	                                                           param,
 	                                                           param);
 	                                                           param);
 
 
-	cleanup_fortunes(&fortune_ctx->generator, fortune_ctx->req);
 	send_error(BAD_GATEWAY, error_string, fortune_ctx->req);
 	send_error(BAD_GATEWAY, error_string, fortune_ctx->req);
 }
 }
 
 
@@ -236,37 +209,45 @@ static result_return_t on_fortune_result(db_query_param_t *param, PGresult *resu
 		ret = SUCCESS;
 		ret = SUCCESS;
 
 
 		for (size_t i = 0; i < num_rows; i++) {
 		for (size_t i = 0; i < num_rows; i++) {
+			const char * const message_data = PQgetvalue(result, i, 1);
+			h2o_iovec_t message = h2o_htmlescape(&fortune_ctx->req->pool,
+			                                     message_data,
+			                                     PQgetlength(result, i, 1));
+			const size_t id_len = PQgetlength(result, i, 0);
+			const size_t fortune_size = offsetof(fortune_t, data) + id_len +
+			                            (message_data == message.base ? message.len : 0);
 			fortune_t * const fortune = h2o_mem_alloc_pool(&fortune_ctx->req->pool,
 			fortune_t * const fortune = h2o_mem_alloc_pool(&fortune_ctx->req->pool,
-			                                               sizeof(*fortune));
+			                                               fortune_size);
 
 
 			if (fortune) {
 			if (fortune) {
-				memset(fortune, 0, sizeof(*fortune));
-				fortune->id.base = PQgetvalue(result, i, 0);
-				fortune->id.len = PQgetlength(result, i, 0);
-				fortune->message = h2o_htmlescape(&fortune_ctx->req->pool,
-				                                  PQgetvalue(result, i, 1),
-				                                  PQgetlength(result, i, 1));
+				memset(fortune, 0, offsetof(fortune_t, data));
+				memcpy(fortune->data, PQgetvalue(result, i, 0), id_len);
+				fortune->id.base = fortune->data;
+				fortune->id.len = id_len;
+
+				if (message_data == message.base) {
+					message.base = fortune->data + id_len;
+					memcpy(message.base, message_data, message.len);
+				}
+
+				fortune->message = message;
 				fortune->l.next = fortune_ctx->result;
 				fortune->l.next = fortune_ctx->result;
 				fortune_ctx->result = &fortune->l;
 				fortune_ctx->result = &fortune->l;
 				fortune_ctx->num_result++;
 				fortune_ctx->num_result++;
-
-				if (!i)
-					fortune->data = result;
 			}
 			}
 			else {
 			else {
-				cleanup_fortunes(&fortune_ctx->generator, fortune_ctx->req);
 				send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, fortune_ctx->req);
 				send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, fortune_ctx->req);
 				ret = DONE;
 				ret = DONE;
-
-				if (!i)
-					PQclear(result);
-
 				break;
 				break;
 			}
 			}
 		}
 		}
+
+		PQclear(result);
 	}
 	}
-	else if (result)
+	else if (result) {
 		PQclear(result);
 		PQclear(result);
+		send_error(BAD_GATEWAY, PQresultErrorMessage(result), fortune_ctx->req);
+	}
 	else {
 	else {
 		mustache_api_t api = {.sectget = on_fortune_section,
 		mustache_api_t api = {.sectget = on_fortune_section,
 		                      .varget = on_fortune_variable,
 		                      .varget = on_fortune_variable,
@@ -286,18 +267,15 @@ static result_return_t on_fortune_result(db_query_param_t *param, PGresult *resu
 
 
 		if (mustache_render(&api, fortune_ctx, ctx->global_data->fortunes_template)) {
 		if (mustache_render(&api, fortune_ctx, ctx->global_data->fortunes_template)) {
 			fortune_ctx->iovec_list = iovec_list->l.next;
 			fortune_ctx->iovec_list = iovec_list->l.next;
-			set_default_response_param(HTML, fortune_ctx->req);
+			set_default_response_param(HTML, fortune_ctx->content_length, fortune_ctx->req);
 			h2o_start_response(fortune_ctx->req, &fortune_ctx->generator);
 			h2o_start_response(fortune_ctx->req, &fortune_ctx->generator);
 			h2o_send(fortune_ctx->req,
 			h2o_send(fortune_ctx->req,
 			         iovec_list->iov,
 			         iovec_list->iov,
 			         iovec_list->iovcnt,
 			         iovec_list->iovcnt,
-			         false);
+			         !fortune_ctx->iovec_list);
 		}
 		}
-		else {
-			cleanup_fortunes(&fortune_ctx->generator, fortune_ctx->req);
+		else
 			send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, fortune_ctx->req);
 			send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, fortune_ctx->req);
-			ret = DONE;
-		}
 	}
 	}
 
 
 	return ret;
 	return ret;
@@ -335,7 +313,6 @@ static void on_fortune_timeout(db_query_param_t *param)
 	                                                           param,
 	                                                           param,
 	                                                           param);
 	                                                           param);
 
 
-	cleanup_fortunes(&fortune_ctx->generator, fortune_ctx->req);
 	send_error(GATEWAY_TIMEOUT, DB_TIMEOUT_ERROR, fortune_ctx->req);
 	send_error(GATEWAY_TIMEOUT, DB_TIMEOUT_ERROR, fortune_ctx->req);
 }
 }
 
 
@@ -401,7 +378,6 @@ int fortunes(struct st_h2o_handler_t *self, h2o_req_t *req)
 			fortune->message.len = sizeof(NEW_FORTUNE_MESSAGE) - 1;
 			fortune->message.len = sizeof(NEW_FORTUNE_MESSAGE) - 1;
 			memset(fortune_ctx, 0, sizeof(*fortune_ctx));
 			memset(fortune_ctx, 0, sizeof(*fortune_ctx));
 			fortune_ctx->generator.proceed = complete_fortunes;
 			fortune_ctx->generator.proceed = complete_fortunes;
-			fortune_ctx->generator.stop = cleanup_fortunes;
 			fortune_ctx->num_result = 1;
 			fortune_ctx->num_result = 1;
 			fortune_ctx->param.command = FORTUNE_TABLE_NAME;
 			fortune_ctx->param.command = FORTUNE_TABLE_NAME;
 			fortune_ctx->param.on_error = on_fortune_error;
 			fortune_ctx->param.on_error = on_fortune_error;

+ 1 - 1
frameworks/C/h2o/src/fortune.h

@@ -28,9 +28,9 @@
 
 
 typedef struct {
 typedef struct {
 	list_t l;
 	list_t l;
-	PGresult *data;
 	h2o_iovec_t id;
 	h2o_iovec_t id;
 	h2o_iovec_t message;
 	h2o_iovec_t message;
+	char data[];
 } fortune_t;
 } fortune_t;
 
 
 int fortunes(struct st_h2o_handler_t *self, h2o_req_t *req);
 int fortunes(struct st_h2o_handler_t *self, h2o_req_t *req);

+ 35 - 51
frameworks/C/h2o/src/request_handler.c

@@ -20,6 +20,7 @@
 #include <assert.h>
 #include <assert.h>
 #include <h2o.h>
 #include <h2o.h>
 #include <stdalign.h>
 #include <stdalign.h>
+#include <stdint.h>
 #include <string.h>
 #include <string.h>
 #include <yajl/yajl_gen.h>
 #include <yajl/yajl_gen.h>
 
 
@@ -29,56 +30,29 @@
 #include "utility.h"
 #include "utility.h"
 #include "world.h"
 #include "world.h"
 
 
-typedef struct {
-	yajl_gen gen;
-	h2o_generator_t h2o_generator;
-} json_ctx_t;
+#define HELLO_RESPONSE "Hello, World!"
 
 
-static void cleanup_json_response(struct st_h2o_generator_t *self, h2o_req_t *req);
-static void complete_json_response(struct st_h2o_generator_t *self, h2o_req_t *req);
 static int json_serializer(struct st_h2o_handler_t *self, h2o_req_t *req);
 static int json_serializer(struct st_h2o_handler_t *self, h2o_req_t *req);
 static int plaintext(struct st_h2o_handler_t *self, h2o_req_t *req);
 static int plaintext(struct st_h2o_handler_t *self, h2o_req_t *req);
 static const char *status_code_to_string(http_status_code_t status_code);
 static const char *status_code_to_string(http_status_code_t status_code);
 
 
-static void cleanup_json_response(struct st_h2o_generator_t *self, h2o_req_t *req)
-{
-	IGNORE_FUNCTION_PARAMETER(req);
-
-	json_ctx_t * const json_ctx = H2O_STRUCT_FROM_MEMBER(json_ctx_t, h2o_generator, self);
-
-	yajl_gen_free(json_ctx->gen);
-}
-
-static void complete_json_response(struct st_h2o_generator_t *self, h2o_req_t *req)
-{
-	h2o_send(req, NULL, 0, true);
-	cleanup_json_response(self, req);
-}
-
 static int json_serializer(struct st_h2o_handler_t *self, h2o_req_t *req)
 static int json_serializer(struct st_h2o_handler_t *self, h2o_req_t *req)
 {
 {
 	IGNORE_FUNCTION_PARAMETER(self);
 	IGNORE_FUNCTION_PARAMETER(self);
 
 
-	json_ctx_t * const json_ctx = h2o_mem_alloc_pool(&req->pool, sizeof(*json_ctx));
-
-	if (json_ctx) {
-		memset(json_ctx, 0, sizeof(*json_ctx));
-		json_ctx->gen = get_json_generator(&req->pool);
-		json_ctx->h2o_generator.proceed = complete_json_response;
-		json_ctx->h2o_generator.stop = cleanup_json_response;
+	const yajl_gen gen = get_json_generator(&req->pool);
 
 
-		if (json_ctx->gen) {
-			CHECK_YAJL_STATUS(yajl_gen_map_open, json_ctx->gen);
-			CHECK_YAJL_STATUS(yajl_gen_string, json_ctx->gen, YAJL_STRLIT("message"));
-			CHECK_YAJL_STATUS(yajl_gen_string, json_ctx->gen, YAJL_STRLIT("Hello, World!"));
-			CHECK_YAJL_STATUS(yajl_gen_map_close, json_ctx->gen);
+	if (gen) {
+		CHECK_YAJL_STATUS(yajl_gen_map_open, gen);
+		CHECK_YAJL_STATUS(yajl_gen_string, gen, YAJL_STRLIT("message"));
+		CHECK_YAJL_STATUS(yajl_gen_string, gen, YAJL_STRLIT(HELLO_RESPONSE));
+		CHECK_YAJL_STATUS(yajl_gen_map_close, gen);
 
 
-			if (!send_json_response(json_ctx->gen, &json_ctx->h2o_generator, req))
-				return 0;
+		if (!send_json_response(gen, NULL, req))
+			return 0;
 
 
 error_yajl:
 error_yajl:
-			yajl_gen_free(json_ctx->gen);
-		}
+		yajl_gen_free(gen);
 	}
 	}
 
 
 	send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, req);
 	send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, req);
@@ -88,8 +62,8 @@ error_yajl:
 static int plaintext(struct st_h2o_handler_t *self, h2o_req_t *req)
 static int plaintext(struct st_h2o_handler_t *self, h2o_req_t *req)
 {
 {
 	IGNORE_FUNCTION_PARAMETER(self);
 	IGNORE_FUNCTION_PARAMETER(self);
-	set_default_response_param(PLAIN, req);
-	h2o_send_inline(req, H2O_STRLIT("Hello, World!"));
+	set_default_response_param(PLAIN, sizeof(HELLO_RESPONSE) - 1, req);
+	h2o_send_inline(req, H2O_STRLIT(HELLO_RESPONSE));
 	return 0;
 	return 0;
 }
 }
 
 
@@ -197,20 +171,29 @@ void send_error(http_status_code_t status_code, const char *body, h2o_req_t *req
 
 
 int send_json_response(yajl_gen gen, h2o_generator_t *h2o_generator, h2o_req_t *req)
 int send_json_response(yajl_gen gen, h2o_generator_t *h2o_generator, h2o_req_t *req)
 {
 {
+	const unsigned char *buf;
 	h2o_iovec_t h2o_iovec = {.len = 0};
 	h2o_iovec_t h2o_iovec = {.len = 0};
 	int ret = EXIT_FAILURE;
 	int ret = EXIT_FAILURE;
 
 
-	static_assert(sizeof(h2o_iovec.base) == sizeof(const unsigned char *) &&
-	              alignof(h2o_iovec.base) == alignof(const unsigned char *),
-	              "Types must be compatible.");
-
-	if (yajl_gen_get_buf(gen,
-	                     (const unsigned char **) &h2o_iovec.base,
-	                     &h2o_iovec.len) == yajl_gen_status_ok) {
-		set_default_response_param(JSON, req);
-		h2o_start_response(req, h2o_generator);
-		h2o_send(req, &h2o_iovec, 1, false);
-		ret = EXIT_SUCCESS;
+	if (yajl_gen_get_buf(gen, &buf, &h2o_iovec.len) == yajl_gen_status_ok) {
+		if (h2o_generator) {
+			h2o_iovec.base = (char *) buf;
+			set_default_response_param(JSON, SIZE_MAX, req);
+			h2o_start_response(req, h2o_generator);
+			h2o_send(req, &h2o_iovec, 1, false);
+			ret = EXIT_SUCCESS;
+		}
+		else {
+			h2o_iovec.base = h2o_mem_alloc_pool(&req->pool, h2o_iovec.len);
+
+			if (h2o_iovec.base) {
+				memcpy(h2o_iovec.base, buf, h2o_iovec.len);
+				yajl_gen_free(gen);
+				set_default_response_param(JSON, h2o_iovec.len, req);
+				h2o_send_inline(req, h2o_iovec.base, h2o_iovec.len);
+				ret = EXIT_SUCCESS;
+			}
+		}
 	}
 	}
 
 
 	return ret;
 	return ret;
@@ -228,8 +211,9 @@ void send_service_unavailable_error(const char *body, h2o_req_t *req)
 	                   H2O_SEND_ERROR_KEEP_HEADERS);
 	                   H2O_SEND_ERROR_KEEP_HEADERS);
 }
 }
 
 
-void set_default_response_param(content_type_t content_type, h2o_req_t *req)
+void set_default_response_param(content_type_t content_type, size_t content_length, h2o_req_t *req)
 {
 {
+	req->res.content_length = content_length;
 	req->res.status = OK;
 	req->res.status = OK;
 	req->res.reason = status_code_to_string(req->res.status);
 	req->res.reason = status_code_to_string(req->res.status);
 
 

+ 3 - 1
frameworks/C/h2o/src/request_handler.h

@@ -46,6 +46,8 @@ void register_request_handlers(h2o_hostconf_t *hostconf, h2o_access_log_filehand
 void send_error(http_status_code_t status_code, const char *body, h2o_req_t *req);
 void send_error(http_status_code_t status_code, const char *body, h2o_req_t *req);
 int send_json_response(yajl_gen gen, h2o_generator_t *h2o_generator, h2o_req_t *req);
 int send_json_response(yajl_gen gen, h2o_generator_t *h2o_generator, h2o_req_t *req);
 void send_service_unavailable_error(const char *body, h2o_req_t *req);
 void send_service_unavailable_error(const char *body, h2o_req_t *req);
-void set_default_response_param(content_type_t content_type, h2o_req_t *req);
+void set_default_response_param(content_type_t content_type,
+                                size_t content_length,
+                                h2o_req_t *req);
 
 
 #endif // REQUEST_H_
 #endif // REQUEST_H_

+ 8 - 2
frameworks/C/h2o/src/template.c

@@ -46,7 +46,10 @@ static uintmax_t read_template(mustache_api_t *api,
                                void *userdata,
                                void *userdata,
                                char *buffer,
                                char *buffer,
                                uintmax_t buffer_size);
                                uintmax_t buffer_size);
-static void template_error(mustache_api_t *api, void *userdata, uintmax_t lineno, char *error);
+static void template_error(mustache_api_t *api,
+                           void *userdata,
+                           uintmax_t lineno,
+                           const char *error);
 
 
 static uintmax_t prerender_section(mustache_api_t *api,
 static uintmax_t prerender_section(mustache_api_t *api,
                                    void *userdata,
                                    void *userdata,
@@ -101,7 +104,10 @@ static uintmax_t read_template(mustache_api_t *api,
 	return fread(buffer, sizeof(*buffer), buffer_size, template_input->input);
 	return fread(buffer, sizeof(*buffer), buffer_size, template_input->input);
 }
 }
 
 
-static void template_error(mustache_api_t *api, void *userdata, uintmax_t lineno, char *error)
+static void template_error(mustache_api_t *api,
+                           void *userdata,
+                           uintmax_t lineno,
+                           const char *error)
 {
 {
 	IGNORE_FUNCTION_PARAMETER(api);
 	IGNORE_FUNCTION_PARAMETER(api);
 
 

+ 5 - 28
frameworks/C/h2o/src/world.c

@@ -54,7 +54,6 @@ typedef struct {
 typedef struct {
 typedef struct {
 	db_query_param_t param;
 	db_query_param_t param;
 	yajl_gen gen;
 	yajl_gen gen;
-	h2o_generator_t h2o_generator;
 	const char *id_pointer;
 	const char *id_pointer;
 	h2o_req_t *req;
 	h2o_req_t *req;
 	uint32_t id;
 	uint32_t id;
@@ -70,8 +69,6 @@ typedef struct {
 	query_result_t res[];
 	query_result_t res[];
 } multiple_query_ctx_t;
 } multiple_query_ctx_t;
 
 
-static void complete_request(struct st_h2o_generator_t *self, h2o_req_t *req);
-static void cleanup_request(struct st_h2o_generator_t *self, h2o_req_t *req);
 static int do_multiple_queries(update_state_t update_state, h2o_req_t *req);
 static int do_multiple_queries(update_state_t update_state, h2o_req_t *req);
 static int initialize_single_query_context(h2o_req_t *req,
 static int initialize_single_query_context(h2o_req_t *req,
                                            on_result_t on_result,
                                            on_result_t on_result,
@@ -85,27 +82,9 @@ static int on_update_write_ready(db_query_param_t *param, PGconn *db_conn);
 static int serialize_item(uint32_t id, uint32_t random_number, yajl_gen gen);
 static int serialize_item(uint32_t id, uint32_t random_number, yajl_gen gen);
 static void serialize_items(const query_result_t *res,
 static void serialize_items(const query_result_t *res,
                             size_t num_result,
                             size_t num_result,
-                            h2o_generator_t *h2o_generator,
                             yajl_gen gen,
                             yajl_gen gen,
                             h2o_req_t *req);
                             h2o_req_t *req);
 
 
-static void cleanup_request(struct st_h2o_generator_t *self, h2o_req_t *req)
-{
-	IGNORE_FUNCTION_PARAMETER(req);
-
-	single_query_ctx_t * const query_ctx = H2O_STRUCT_FROM_MEMBER(single_query_ctx_t,
-	                                                              h2o_generator,
-	                                                              self);
-
-	yajl_gen_free(query_ctx->gen);
-}
-
-static void complete_request(struct st_h2o_generator_t *self, h2o_req_t *req)
-{
-	h2o_send(req, NULL, 0, true);
-	cleanup_request(self, req);
-}
-
 static int do_multiple_queries(update_state_t update_state, h2o_req_t *req)
 static int do_multiple_queries(update_state_t update_state, h2o_req_t *req)
 {
 {
 	thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t,
 	thread_context_t * const ctx = H2O_STRUCT_FROM_MEMBER(thread_context_t,
@@ -178,8 +157,6 @@ static int initialize_single_query_context(h2o_req_t *req,
 	query_ctx->gen = get_json_generator(&req->pool);
 	query_ctx->gen = get_json_generator(&req->pool);
 
 
 	if (query_ctx->gen) {
 	if (query_ctx->gen) {
-		query_ctx->h2o_generator.proceed = complete_request;
-		query_ctx->h2o_generator.stop = cleanup_request;
 		query_ctx->id_format = 1;
 		query_ctx->id_format = 1;
 		query_ctx->id_len = sizeof(query_ctx->id);
 		query_ctx->id_len = sizeof(query_ctx->id);
 		query_ctx->id_pointer = (const char *) &query_ctx->id;
 		query_ctx->id_pointer = (const char *) &query_ctx->id;
@@ -251,7 +228,6 @@ static result_return_t on_multiple_query_result(db_query_param_t *param, PGresul
 		else if (query_ctx->update_state == NO_UPDATE) {
 		else if (query_ctx->update_state == NO_UPDATE) {
 			serialize_items(query_ctx->res,
 			serialize_items(query_ctx->res,
 			                query_ctx->num_result,
 			                query_ctx->num_result,
-			                &query_ctx->single.h2o_generator,
 			                query_ctx->single.gen,
 			                query_ctx->single.gen,
 			                query_ctx->single.req);
 			                query_ctx->single.req);
 			return DONE;
 			return DONE;
@@ -300,7 +276,7 @@ static result_return_t on_single_query_result(db_query_param_t *param, PGresult
 		PQclear(result);
 		PQclear(result);
 
 
 		if (!serialize_item(ntohl(query_ctx->id), random_number, query_ctx->gen) &&
 		if (!serialize_item(ntohl(query_ctx->id), random_number, query_ctx->gen) &&
-		    !send_json_response(query_ctx->gen, &query_ctx->h2o_generator, query_ctx->req))
+		    !send_json_response(query_ctx->gen, NULL, query_ctx->req))
 			return DONE;
 			return DONE;
 
 
 		send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, query_ctx->req);
 		send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, query_ctx->req);
@@ -342,7 +318,6 @@ static result_return_t on_update_result(db_query_param_t *param, PGresult *resul
 
 
 			serialize_items(query_ctx->res,
 			serialize_items(query_ctx->res,
 			                query_ctx->num_result,
 			                query_ctx->num_result,
-			                &query_ctx->single.h2o_generator,
 			                query_ctx->single.gen,
 			                query_ctx->single.gen,
 			                query_ctx->single.req);
 			                query_ctx->single.req);
 			ret = DONE;
 			ret = DONE;
@@ -354,6 +329,7 @@ static result_return_t on_update_result(db_query_param_t *param, PGresult *resul
 	PQclear(result);
 	PQclear(result);
 	return ret;
 	return ret;
 error:
 error:
+	yajl_gen_free(query_ctx->single.gen);
 	send_error(BAD_GATEWAY, PQresultErrorMessage(result), query_ctx->single.req);
 	send_error(BAD_GATEWAY, PQresultErrorMessage(result), query_ctx->single.req);
 	PQclear(result);
 	PQclear(result);
 	return DONE;
 	return DONE;
@@ -440,7 +416,6 @@ error_yajl:
 
 
 static void serialize_items(const query_result_t *res,
 static void serialize_items(const query_result_t *res,
                             size_t num_result,
                             size_t num_result,
-                            h2o_generator_t *h2o_generator,
                             yajl_gen gen,
                             yajl_gen gen,
                             h2o_req_t *req)
                             h2o_req_t *req)
 {
 {
@@ -452,9 +427,11 @@ static void serialize_items(const query_result_t *res,
 
 
 	CHECK_YAJL_STATUS(yajl_gen_array_close, gen);
 	CHECK_YAJL_STATUS(yajl_gen_array_close, gen);
 
 
-	if (send_json_response(gen, h2o_generator, req))
+	if (send_json_response(gen, NULL, req)) {
 error_yajl:
 error_yajl:
+		yajl_gen_free(gen);
 		send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, req);
 		send_error(INTERNAL_SERVER_ERROR, MEM_ALLOC_ERR_MSG, req);
+	}
 }
 }
 
 
 int multiple_queries(struct st_h2o_handler_t *self, h2o_req_t *req)
 int multiple_queries(struct st_h2o_handler_t *self, h2o_req_t *req)

+ 7 - 9
frameworks/Go/falcore/src/framework_benchmarks/falcore.go

@@ -148,14 +148,10 @@ var requiredHeaders = falcore.NewResponseFilter(func(req *falcore.Request, res *
 	res.Header.Set("Date", time.Now().Format(time.RFC1123))
 	res.Header.Set("Date", time.Now().Format(time.RFC1123))
 })
 })
 
 
-var applicationJson = http.Header{"Content-Type": []string{"application/json"}}
-var textPlain = http.Header{"Content-Type": []string{"text/plain"}}
-var textHtml = http.Header{"Content-Type": []string{"text/html"}}
-
 // Test 1: JSON serialization
 // Test 1: JSON serialization
 var jsonFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Response {
 var jsonFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Response {
 	if req.HttpRequest.URL.Path == "/json" {
 	if req.HttpRequest.URL.Path == "/json" {
-		resp, _ := responder.JSONResponse(req.HttpRequest, 200, applicationJson, &Message{helloWorldString})
+		resp, _ := responder.JSONResponse(req.HttpRequest, 200, nil, &Message{helloWorldString})
 		return resp
 		return resp
 	}
 	}
 	return nil
 	return nil
@@ -170,7 +166,7 @@ var dbFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Respons
 			log.Fatalf("Error scanning world row: %s", err.Error())
 			log.Fatalf("Error scanning world row: %s", err.Error())
 		}
 		}
 
 
-		resp, _ := responder.JSONResponse(req.HttpRequest, 200, applicationJson, &world)
+		resp, _ := responder.JSONResponse(req.HttpRequest, 200, nil, &world)
 		return resp
 		return resp
 	}
 	}
 	return nil
 	return nil
@@ -204,7 +200,7 @@ var queriesFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Re
 				log.Fatalf("Error scanning world row: %s", err.Error())
 				log.Fatalf("Error scanning world row: %s", err.Error())
 			}
 			}
 		}
 		}
-		resp, _ := responder.JSONResponse(req.HttpRequest, 200, applicationJson, &world)
+		resp, _ := responder.JSONResponse(req.HttpRequest, 200, nil, &world)
 		return resp
 		return resp
 	}
 	}
 	return nil
 	return nil
@@ -236,6 +232,7 @@ var fortuneFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Re
 			pipeWriter.Close()
 			pipeWriter.Close()
 		}()
 		}()
 
 
+		textHtml := http.Header{"Content-Type": []string{"text/html"}}
 		return falcore.SimpleResponse(req.HttpRequest, 200, textHtml, -1, pipeReader)
 		return falcore.SimpleResponse(req.HttpRequest, 200, textHtml, -1, pipeReader)
 	}
 	}
 	return nil
 	return nil
@@ -254,7 +251,7 @@ var updateFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Res
 			worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber)
 			worldStatement.QueryRow(rand.Intn(worldRowCount)+1).Scan(&world.Id, &world.RandomNumber)
 			world.RandomNumber = uint16(rand.Intn(worldRowCount) + 1)
 			world.RandomNumber = uint16(rand.Intn(worldRowCount) + 1)
 			updateStatement.Exec(world.RandomNumber, world.Id)
 			updateStatement.Exec(world.RandomNumber, world.Id)
-			resp, _ := responder.JSONResponse(req.HttpRequest, 200, applicationJson, &world)
+			resp, _ := responder.JSONResponse(req.HttpRequest, 200, nil, &world)
 			return resp
 			return resp
 		} else {
 		} else {
 			world := make([]World, n)
 			world := make([]World, n)
@@ -267,7 +264,7 @@ var updateFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Res
 					log.Fatalf("Error updating world row: %s", err.Error())
 					log.Fatalf("Error updating world row: %s", err.Error())
 				}
 				}
 			}
 			}
-			resp, _ := responder.JSONResponse(req.HttpRequest, 200, applicationJson, world)
+			resp, _ := responder.JSONResponse(req.HttpRequest, 200, nil, world)
 			return resp
 			return resp
 		}
 		}
 
 
@@ -278,6 +275,7 @@ var updateFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Res
 // Test 6: Plaintext
 // Test 6: Plaintext
 var plaintextFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Response {
 var plaintextFilter = falcore.NewRequestFilter(func(req *falcore.Request) *http.Response {
 	if req.HttpRequest.URL.Path == "/plaintext" {
 	if req.HttpRequest.URL.Path == "/plaintext" {
+		textPlain := http.Header{"Content-Type": []string{"text/plain"}}
 		return falcore.ByteResponse(req.HttpRequest, 200, textPlain, helloWorldBytes)
 		return falcore.ByteResponse(req.HttpRequest, 200, textPlain, helloWorldBytes)
 	}
 	}
 	return nil
 	return nil

+ 1 - 1
frameworks/Go/fasthttp/setup-mysql-prefork.sh

@@ -5,7 +5,7 @@ sed -i 's|tcp(.*:3306)|tcp('"${DBHOST}"':3306)|g' src/server-mysql/server.go
 fw_depends go
 fw_depends go
 
 
 GOPATH=`pwd` go get -u github.com/go-sql-driver/mysql
 GOPATH=`pwd` go get -u github.com/go-sql-driver/mysql
-GOPATH=`pwd` go get -u github.com/valyala/fasthttp
+GOPATH=`pwd` go get -u github.com/valyala/fasthttp/...
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 
 
 rm -f ./server-mysql
 rm -f ./server-mysql

+ 1 - 1
frameworks/Go/fasthttp/setup-mysql.sh

@@ -5,7 +5,7 @@ sed -i 's|tcp(.*:3306)|tcp('"${DBHOST}"':3306)|g' src/server-mysql/server.go
 fw_depends go
 fw_depends go
 
 
 GOPATH=`pwd` go get -u github.com/go-sql-driver/mysql
 GOPATH=`pwd` go get -u github.com/go-sql-driver/mysql
-GOPATH=`pwd` go get -u github.com/valyala/fasthttp
+GOPATH=`pwd` go get -u github.com/valyala/fasthttp/...
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 
 
 rm -f ./server-mysql
 rm -f ./server-mysql

+ 1 - 1
frameworks/Go/fasthttp/setup-postgresql-prefork.sh

@@ -5,7 +5,7 @@ sed -i 's|localhost|'"${DBHOST}"'|g' src/server-postgresql/server.go
 fw_depends go
 fw_depends go
 
 
 GOPATH=`pwd` go get -u github.com/jackc/pgx
 GOPATH=`pwd` go get -u github.com/jackc/pgx
-GOPATH=`pwd` go get -u github.com/valyala/fasthttp
+GOPATH=`pwd` go get -u github.com/valyala/fasthttp/...
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 
 
 rm -f ./server-postgresql
 rm -f ./server-postgresql

+ 1 - 1
frameworks/Go/fasthttp/setup-postgresql.sh

@@ -5,7 +5,7 @@ sed -i 's|localhost|'"${DBHOST}"'|g' src/server-postgresql/server.go
 fw_depends go
 fw_depends go
 
 
 GOPATH=`pwd` go get -u github.com/jackc/pgx
 GOPATH=`pwd` go get -u github.com/jackc/pgx
-GOPATH=`pwd` go get -u github.com/valyala/fasthttp
+GOPATH=`pwd` go get -u github.com/valyala/fasthttp/...
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 GOPATH=`pwd` go get -u github.com/valyala/quicktemplate/qtc
 
 
 rm -f ./server-postgresql
 rm -f ./server-postgresql

+ 2 - 0
frameworks/Java/jooby/setup.sh

@@ -2,6 +2,8 @@
 
 
 fw_depends java maven
 fw_depends java maven
 
 
+sed -i 's|localhost|'"${DBHOST}"'|g' conf/application.conf
+
 mvn clean package
 mvn clean package
 
 
 cd target
 cd target

+ 0 - 101
frameworks/Java/sabina/benchmark_config.json

@@ -1,101 +0,0 @@
-{
-  "framework": "sabina",
-  "tests": [{
-    "default": {
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-
-      "port": 5050,
-      "setup_file": "undertow-mongodb",
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MongoDB",
-      "framework": "Sabina",
-      "language": "Java",
-      "orm": "Raw",
-      "platform": "Servlet",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "Sabina Undertow MongoDB",
-      "notes": "",
-      "versus": "servlet"
-    },
-    "undertow-mysql": {
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-
-      "port": 5050,
-      "setup_file": "undertow",
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "Sabina",
-      "language": "Java",
-      "orm": "Raw",
-      "platform": "Servlet",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "Sabina Undertow MySQL",
-      "notes": "",
-      "versus": "servlet"
-    },
-    "jetty-mysql": {
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-
-      "port": 5050,
-      "setup_file": "jetty",
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "Sabina",
-      "language": "Java",
-      "orm": "Raw",
-      "platform": "Servlet",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "Sabina Jetty MySQL",
-      "notes": "",
-      "versus": "servlet"
-    },
-    "jetty-mongodb": {
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-
-      "port": 5050,
-      "setup_file": "jetty-mongodb",
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MongoDB",
-      "framework": "Sabina",
-      "language": "Java",
-      "orm": "Raw",
-      "platform": "Servlet",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "Sabina Jetty MongoDB",
-      "notes": "",
-      "versus": "servlet"
-    }
-  }]
-}

+ 0 - 5
frameworks/Java/sabina/jetty-mongodb.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-
-fw_depends java maven
-
-./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mongodb

+ 0 - 5
frameworks/Java/sabina/jetty.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-
-fw_depends java maven
-
-./setup.sh -Dsabina.backend=jetty -Dsabina.benchmark.repository=mysql

+ 0 - 179
frameworks/Java/sabina/pom.xml

@@ -1,179 +0,0 @@
-<!--
- ! Copyright © 2015 Juan José Aguililla. All rights reserved.
- !
- ! 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.
- !-->
-
-<project
-    xmlns="http://maven.apache.org/POM/4.0.0"
-    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>sabina</groupId>
-    <artifactId>sabina</artifactId>
-    <version>1.0.0</version>
-
-    <name>Sabina benchmark project</name>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
-        <maven.compiler.source>${java.specification.version}</maven.compiler.source>
-        <maven.compiler.target>${java.specification.version}</maven.compiler.target>
-        <maven.compiler.debug>false</maven.compiler.debug>
-
-        <db.host>localhost</db.host>
-
-        <sabina-version>1.3.5</sabina-version>
-    </properties>
-
-    <repositories>
-        <repository>
-            <snapshots>
-                <enabled>false</enabled>
-            </snapshots>
-            <id>central</id>
-            <name>bintray</name>
-            <url>http://jcenter.bintray.com</url>
-        </repository>
-    </repositories>
-    <pluginRepositories>
-        <pluginRepository>
-            <snapshots>
-                <enabled>false</enabled>
-            </snapshots>
-            <id>central</id>
-            <name>bintray-plugins</name>
-            <url>http://jcenter.bintray.com</url>
-        </pluginRepository>
-    </pluginRepositories>
-
-    <dependencies>
-        <dependency>
-            <groupId>sabina</groupId>
-            <artifactId>http</artifactId>
-            <version>${sabina-version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>javax.servlet</groupId>
-                    <artifactId>javax.servlet-api</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>sabina</groupId>
-            <artifactId>extra</artifactId>
-            <version>${sabina-version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.jboss.spec.javax.servlet</groupId>
-            <artifactId>jboss-servlet-api_3.1_spec</artifactId>
-            <version>1.0.0.Final</version>
-        </dependency>
-        <dependency>
-            <groupId>com.mchange</groupId>
-            <artifactId>c3p0</artifactId>
-            <version>0.9.2.1</version>
-        </dependency>
-        <dependency>
-            <groupId>mysql</groupId>
-            <artifactId>mysql-connector-java</artifactId>
-            <version>5.1.38</version>
-        </dependency>
-        <dependency>
-            <groupId>org.mongodb</groupId>
-            <artifactId>mongo-java-driver</artifactId>
-            <version>3.0.0</version>
-        </dependency>
-
-        <dependency>
-            <groupId>org.testng</groupId>
-            <artifactId>testng</artifactId>
-            <version>6.8.21</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>fluent-hc</artifactId>
-            <version>4.3.3</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-            </resource>
-        </resources>
-
-        <plugins>
-            <plugin>
-                <artifactId>maven-shade-plugin</artifactId>
-                <version>2.3</version>
-                <configuration>
-                    <createDependencyReducedPom>false</createDependencyReducedPom>
-                </configuration>
-                <executions>
-                    <execution>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>shade</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <artifactId>maven-jar-plugin</artifactId>
-                <version>2.5</version>
-                <configuration>
-                    <archive>
-                        <manifest>
-                            <mainClass>sabina.benchmark.Application</mainClass>
-                        </manifest>
-                    </archive>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-war-plugin</artifactId>
-                <version>2.6</version>
-                <configuration>
-                    <warName>ROOT</warName>
-                    <failOnMissingWebXml>false</failOnMissingWebXml>
-                    <packagingExcludes>
-                        WEB-INF/lib/jetty-*.jar,
-                        WEB-INF/lib/undertow-*.jar,
-                        WEB-INF/lib/freemarker-*.jar,
-                        WEB-INF/lib/rythm-*.jar,
-                        WEB-INF/lib/mysql-*.jar,
-                        WEB-INF/lib/xnio-*.jar,
-                        WEB-INF/lib/scribe-*.jar,
-                        WEB-INF/lib/jboss-*.jar
-                    </packagingExcludes>
-                </configuration>
-                <executions>
-                    <execution>
-                        <id>webapp</id>
-                        <goals>
-                            <goal>war</goal>
-                        </goals>
-                        <phase>package</phase>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>

+ 0 - 40
frameworks/Java/sabina/readme.md

@@ -1,40 +0,0 @@
-
-# Sabina Benchmarking Test
-
-This is the Sabina portion of a [benchmarking test suite](../) comparing a variety of web
-development platforms. The test utilizes Sabina routes, Gson for JSON serialization and a custom
-OSIV pattern created with Sabina filters.
-
-
-## Tests
-
-* [Sabina application](/src/main/java/sabina/benchmark/Application.java)
-
-
-## Infrastructure Software Versions
-
-* [Sabina 1.0](http://there4.co/)
-
-
-## Different test setups
-
-* Local environment with Sabina's built in embedded Jetty (port=8080, context=/)
- * Start application from [Application](/src/main/java/sabina/benchmark/Application.java)'s main method
-* Local environment with Sabina's built in embedded Undertow (port=8080, context=/)
- * Start application from [Application](/src/main/java/sabina/benchmark/Application.java)'s main method
-
-
-## Test URLs
-
-### JSON Encoding Test
-
-http://localhost:8080/json
-
-### Data-Store/Database Mapping Test
-
-http://localhost:8080/db?queries=5
-
-### Plain Text Test
-
-http://localhost:8080/plaintext
-

+ 0 - 4
frameworks/Java/sabina/setup.sh

@@ -1,4 +0,0 @@
-#!/bin/bash
-
-mvn clean package -DskipTests -Ddb.host=${DBHOST}
-$JAVA_HOME/bin/java -jar target/sabina-1.0.0.jar &

+ 0 - 7
frameworks/Java/sabina/source_code

@@ -1,7 +0,0 @@
-./sabina/src/main/java/sabina/benchmark/
-./sabina/src/main/java/sabina/benchmark/Application.java
-./sabina/src/main/java/sabina/benchmark/Message.java
-./sabina/src/main/java/sabina/benchmark/World.java
-./sabina/src/main/java/sabina/benchmark/Fortune.java
-./sabina/src/main/resources/fortunes.mustache
-./sabina/src/main/resources/server.properties

+ 0 - 159
frameworks/Java/sabina/src/main/java/sabina/benchmark/Application.java

@@ -1,159 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-import static java.lang.Integer.parseInt;
-import static java.lang.System.getProperty;
-import static sabina.content.JsonContent.toJson;
-import static sabina.view.MustacheView.renderMustache;
-
-import sabina.Request;
-import sabina.server.ServletApplication;
-
-import java.util.*;
-import java.util.Date;
-import javax.servlet.annotation.WebListener;
-
-@WebListener public final class Application extends sabina.Application {
-    static final String SETTINGS_RESOURCE = "/server.properties";
-    static final int DB_ROWS = 10000;
-
-    private static final String MESSAGE = "Hello, World!";
-    private static final String CONTENT_TYPE_TEXT = "text/plain";
-    private static final String CONTENT_TYPE_JSON = "application/json";
-    private static final String QUERIES_PARAM = "queries";
-
-    static Repository repository = loadRepository ();
-
-    static Properties loadConfiguration () {
-        try {
-            Properties settings = new Properties ();
-            settings.load (Application.class.getResourceAsStream (SETTINGS_RESOURCE));
-            return settings;
-        }
-        catch (Exception ex) {
-            throw new RuntimeException (ex);
-        }
-    }
-
-    static Repository loadRepository () {
-        switch (getProperty ("sabina.benchmark.repository", "mongodb")) {
-            case "mongodb":
-                return new MongoDbRepository (loadConfiguration ());
-            case "mysql":
-            default:
-                return new MySqlRepository (loadConfiguration ());
-        }
-    }
-
-    private Object getDb (Request it) {
-        try {
-            final World[] worlds = repository.getWorlds (getQueries (it), false);
-            it.response.type (CONTENT_TYPE_JSON);
-            return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-        }
-        catch (Exception e) {
-            e.printStackTrace ();
-            return e.getMessage ();
-        }
-    }
-
-    private Object getFortunes (Request it) {
-        try {
-            List<Fortune> fortunes = repository.getFortunes ();
-            fortunes.add (new Fortune (0, "Additional fortune added at request time."));
-            fortunes.sort ((a, b) -> a.message.compareTo (b.message));
-
-            it.response.type ("text/html; charset=utf-8");
-            return renderMustache ("fortunes.mustache", fortunes);
-        }
-        catch (Exception e) {
-            e.printStackTrace ();
-            return e.getMessage ();
-        }
-    }
-
-    private Object getUpdates (Request it) {
-        try {
-            World[] worlds = repository.getWorlds (getQueries (it), true);
-            it.response.type (CONTENT_TYPE_JSON);
-            return toJson (it.queryParams (QUERIES_PARAM) == null? worlds[0] : worlds);
-        }
-        catch (Exception e) {
-            e.printStackTrace ();
-            return e.getMessage ();
-        }
-    }
-
-    private int getQueries (final Request request) {
-        try {
-            String parameter = request.queryParams (QUERIES_PARAM);
-            if (parameter == null)
-                return 1;
-
-            int queries = parseInt (parameter);
-            if (queries < 1)
-                return 1;
-            if (queries > 500)
-                return 500;
-
-            return queries;
-        }
-        catch (NumberFormatException ex) {
-            return 1;
-        }
-    }
-
-    private Object getPlaintext (Request it) {
-        it.response.type (CONTENT_TYPE_TEXT);
-        return MESSAGE;
-    }
-
-    private Object getJson (Request it) {
-        it.response.type (CONTENT_TYPE_JSON);
-        return toJson (new Message ());
-    }
-
-    private void addCommonHeaders (Request it) {
-        it.header ("Server", "Undertow/1.1.2");
-        it.response.addDateHeader ("Date", new Date ().getTime ());
-    }
-
-    public Application () {
-        routes ();
-
-        Properties settings = loadConfiguration ();
-
-        bind (settings.getProperty ("web.host"));
-        port (parseInt (settings.getProperty ("web.port")));
-
-        start ();
-    }
-
-    public static void main (String[] args) {
-        new Application ();
-    }
-
-//    @Override
-    protected void routes () {
-        get ("/json", this::getJson);
-        get ("/db", this::getDb);
-        get ("/query", this::getDb);
-        get ("/fortune", this::getFortunes);
-        get ("/update", this::getUpdates);
-        get ("/plaintext", this::getPlaintext);
-        after (this::addCommonHeaders);
-    }
-}

+ 0 - 25
frameworks/Java/sabina/src/main/java/sabina/benchmark/Fortune.java

@@ -1,25 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-final class Fortune {
-    final int id;
-    final String message;
-
-    Fortune (final int id, final String message) {
-        this.id = id;
-        this.message = message;
-    }
-}

+ 0 - 19
frameworks/Java/sabina/src/main/java/sabina/benchmark/Message.java

@@ -1,19 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-final class Message {
-    final String message = "Hello, World!";
-}

+ 0 - 90
frameworks/Java/sabina/src/main/java/sabina/benchmark/MongoDbRepository.java

@@ -1,90 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-import static com.mongodb.client.model.Filters.eq;
-import static java.lang.Integer.parseInt;
-import static sabina.benchmark.Application.DB_ROWS;
-
-import java.util.*;
-import java.util.concurrent.ThreadLocalRandom;
-
-import com.mongodb.*;
-import com.mongodb.client.MongoCollection;
-import com.mongodb.client.MongoDatabase;
-import org.bson.Document;
-
-final class MongoDbRepository implements Repository {
-    private MongoCollection<Document> worldCollection;
-    private MongoCollection<Document> fortuneCollection;
-
-    MongoDbRepository (Properties settings) {
-        final int PORT = parseInt (settings.getProperty ("mongodb.port"));
-        final String HOST = settings.getProperty ("mongodb.host");
-        final String DATABASE = settings.getProperty ("mongodb.database");
-        final String WORLD = settings.getProperty ("mongodb.world.collection");
-        final String FORTUNE = settings.getProperty ("mongodb.fortune.collection");
-
-        MongoClient mongoClient = new MongoClient (HOST, PORT);
-        MongoDatabase db = mongoClient.getDatabase (DATABASE);
-        worldCollection = db.getCollection (WORLD);
-        fortuneCollection = db.getCollection (FORTUNE);
-    }
-
-    @Override public List<Fortune> getFortunes () {
-        List<Fortune> fortunes = new ArrayList<> ();
-
-        fortuneCollection.find ().forEach ((Block<Document>)doc ->
-            fortunes.add (
-                new Fortune (
-                    doc.get ("_id", Number.class).intValue (),
-                    (String)doc.get ("message")
-                )
-            )
-        );
-
-        return fortunes;
-    }
-
-    @Override public World[] getWorlds (int queries, boolean update) {
-        final World[] worlds = new World[queries];
-        final Random random = ThreadLocalRandom.current ();
-
-        for (int ii = 0; ii < queries; ii++) {
-            int id = random.nextInt (DB_ROWS) + 1;
-            worlds[ii] = update? updateWorld (id, random.nextInt (DB_ROWS) + 1) : findWorld (id);
-        }
-
-        return worlds;
-    }
-
-    private World findWorld (int id) {
-        return createWorld (worldCollection.find(eq ("_id", id)).first ());
-    }
-
-    private World createWorld (Document world) {
-        return new World (
-            world.get ("_id", Number.class).intValue (),
-            world.get ("randomNumber", Number.class).intValue ()
-        );
-    }
-
-    public World updateWorld (int id, int random) {
-        Document newWorld = new Document ("_id", id).append ("randomNumber", random);
-        worldCollection.replaceOne (eq ("_id", id), newWorld);
-
-        return new World (id, random);
-    }
-}

+ 0 - 139
frameworks/Java/sabina/src/main/java/sabina/benchmark/MySqlRepository.java

@@ -1,139 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-import static java.lang.System.getProperty;
-import static sabina.benchmark.Application.DB_ROWS;
-
-import java.sql.*;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-import java.util.concurrent.ThreadLocalRandom;
-
-import javax.sql.DataSource;
-
-import com.mchange.v2.c3p0.ComboPooledDataSource;
-
-final class MySqlRepository implements Repository {
-    private static final boolean AUTOCOMMIT = getProperty ("sabina.benchmark.autocommit") != null;
-    private static final String SELECT_WORLD = "select * from world where id = ?";
-    private static final String UPDATE_WORLD = "update world set randomNumber = ? where id = ?";
-    private static final String SELECT_FORTUNES = "select * from fortune";
-
-    private final DataSource DATA_SOURCE;
-
-    MySqlRepository (Properties settings) {
-        final String jdbcUrl = settings.getProperty ("mysql.uri");
-        DATA_SOURCE = createSessionFactory (jdbcUrl);
-    }
-
-    private DataSource createSessionFactory (String jdbcUrl) {
-        try {
-            ComboPooledDataSource dataSource = new ComboPooledDataSource ();
-            dataSource.setMinPoolSize (32);
-            dataSource.setMaxPoolSize (256);
-            dataSource.setCheckoutTimeout (1800);
-            dataSource.setMaxStatements (50);
-            dataSource.setJdbcUrl (jdbcUrl);
-            return dataSource;
-        }
-        catch (Exception ex) {
-            throw new RuntimeException (ex);
-        }
-    }
-
-    private void commitUpdate (Connection con, PreparedStatement stmtUpdate)
-        throws SQLException {
-        int count = 0;
-        boolean retrying;
-
-        do {
-            try {
-                stmtUpdate.executeBatch ();
-                retrying = false;
-            }
-            catch (BatchUpdateException e) {
-                retrying = true;
-            }
-        }
-        while (count++ < 10 && retrying);
-
-        con.commit ();
-    }
-
-    private void updateWorld (World world, PreparedStatement stmtUpdate)
-        throws SQLException {
-        stmtUpdate.setInt (1, world.randomNumber);
-        stmtUpdate.setInt (2, world.id);
-
-        if (AUTOCOMMIT) {
-            stmtUpdate.executeUpdate ();
-        }
-        else {
-            stmtUpdate.addBatch ();
-        }
-    }
-
-    @Override public List<Fortune> getFortunes () {
-        final List<Fortune> fortunes = new ArrayList<> ();
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            final ResultSet rs = con.prepareStatement (SELECT_FORTUNES).executeQuery ();
-            while (rs.next ())
-                fortunes.add (new Fortune (rs.getInt (1), rs.getString (2)));
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        return fortunes;
-    }
-
-    @Override public World[] getWorlds (int queries, boolean update) {
-        final World[] worlds = new World[queries];
-
-        try (final Connection con = DATA_SOURCE.getConnection ()) {
-            if (update)
-                con.setAutoCommit (AUTOCOMMIT);
-
-            final Random random = ThreadLocalRandom.current ();
-            final PreparedStatement stmtSelect = con.prepareStatement (SELECT_WORLD);
-            final PreparedStatement stmtUpdate = update? con.prepareStatement (UPDATE_WORLD) : null;
-
-            for (int ii = 0; ii < queries; ii++) {
-                stmtSelect.setInt (1, random.nextInt (DB_ROWS) + 1);
-                final ResultSet rs = stmtSelect.executeQuery ();
-                while (rs.next ()) {
-                    worlds[ii] = new World (rs.getInt (1), rs.getInt (2));
-
-                    if (update) {
-                        worlds[ii] = new World (worlds[ii].id, random.nextInt (DB_ROWS) + 1);
-                        updateWorld (worlds[ii], stmtUpdate);
-                    }
-                }
-            }
-
-            if (update && !AUTOCOMMIT)
-                commitUpdate (con, stmtUpdate);
-        }
-        catch (SQLException e) {
-            e.printStackTrace ();
-        }
-
-        return worlds;
-    }
-}

+ 0 - 22
frameworks/Java/sabina/src/main/java/sabina/benchmark/Repository.java

@@ -1,22 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-import java.util.List;
-
-interface Repository {
-    List<Fortune> getFortunes ();
-    World[] getWorlds (int queries, boolean update);
-}

+ 0 - 24
frameworks/Java/sabina/src/main/java/sabina/benchmark/World.java

@@ -1,24 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-final class World {
-    final int id, randomNumber;
-
-    World (final int id, final int randomNumber) {
-        this.id = id;
-        this.randomNumber = randomNumber;
-    }
-}

+ 0 - 20
frameworks/Java/sabina/src/main/resources/fortunes.mustache

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

+ 0 - 42
frameworks/Java/sabina/src/main/resources/server.properties

@@ -1,42 +0,0 @@
-#
-# Copyright \u00A9 2015 Juan Jos\u00E9 Aguililla. All rights reserved.
-#
-# 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.port=5050
-web.host=0.0.0.0
-
-mongodb.host=${db.host}
-mongodb.port=27017
-mongodb.database=hello_world
-mongodb.world.collection=world
-mongodb.fortune.collection=fortune
-
-mysql.uri=jdbc:mysql://${db.host}:3306/hello_world?\
-user=benchmarkdbuser&\
-password=benchmarkdbpass&\
-jdbcCompliantTruncation=false&\
-elideSetAutoCommits=true&\
-useLocalSessionState=true&\
-cachePrepStmts=true&\
-cacheCallableStmts=true&\
-alwaysSendSetIsolation=false&\
-prepStmtCacheSize=4096&\
-cacheServerConfiguration=true&\
-prepStmtCacheSqlLimit=2048&\
-zeroDateTimeBehavior=convertToNull&\
-traceProtocol=false&\
-useUnbufferedInput=false&\
-useReadAheadInput=false&\
-maintainTimeStats=false&\
-useServerPrepStmts&\
-cacheRSMetadata=true

+ 0 - 197
frameworks/Java/sabina/src/test/java/sabina/benchmark/ApplicationTest.java

@@ -1,197 +0,0 @@
-/*
- * Copyright © 2015 Juan José Aguililla. All rights reserved.
- *
- * 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.
- */
-
-package sabina.benchmark;
-
-import static org.apache.http.client.fluent.Request.Get;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-
-import com.google.gson.Gson;
-import org.apache.http.HttpResponse;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * <p>TODO
- * Write article about stress test with TestNG (scenarios, combine different tests in scenarios,
- * adding random pauses...)
- */
-@Test public final class ApplicationTest {
-    private static final String ENDPOINT = "http://localhost:5050";
-    private static final Gson GSON = new Gson ();
-
-    private static Application application;
-
-    @BeforeClass public void setup () throws IOException {
-        application = new Application ();
-    }
-
-    @AfterClass public void close () {
-        application.stop ();
-    }
-
-    public void json () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/json");
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        assert "Hello, World!".equals (GSON.fromJson (content, Map.class).get ("message"));
-    }
-
-    public void plaintext () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/plaintext");
-        String content = getContent (response);
-
-        checkResponse (response, content, "text/plain");
-        assert "Hello, World!".equals (content);
-    }
-
-    public void no_query_parameter () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/db");
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        Map<?, ?> resultsMap = GSON.fromJson (content, Map.class);
-        assert resultsMap.containsKey ("id") && resultsMap.containsKey ("randomNumber");
-    }
-
-    public void empty_query_parameter () throws IOException {
-        checkDbRequest ("/query?queries", 1);
-    }
-
-    public void text_query_parameter () throws IOException {
-        checkDbRequest ("/query?queries=text", 1);
-    }
-
-    public void zero_queries () throws IOException {
-        checkDbRequest ("/query?queries=0", 1);
-    }
-
-    public void one_thousand_queries () throws IOException {
-        checkDbRequest ("/query?queries=1000", 500);
-    }
-
-    public void one_query () throws IOException {
-        checkDbRequest ("/query?queries=1", 1);
-    }
-
-    public void ten_queries () throws IOException {
-        checkDbRequest ("/query?queries=10", 10);
-    }
-
-    public void one_hundred_queries () throws IOException {
-        checkDbRequest ("/query?queries=100", 100);
-    }
-
-    public void five_hundred_queries () throws IOException {
-        checkDbRequest ("/query?queries=500", 500);
-    }
-
-    public void five_hundred_and_one_queries () throws IOException {
-        checkDbRequest ("/query?queries=501", 500);
-    }
-
-    public void fortunes () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/fortune");
-        String content = getContent (response);
-        String contentType = response.getEntity ().getContentType ().getValue ();
-
-        assert response.getFirstHeader ("Server") != null;
-        assert response.getFirstHeader ("Date") != null;
-        assert content.contains ("&lt;script&gt;alert(&quot;This should not be displayed");
-        assert content.contains ("フレームワークのベンチマーク");
-        assert "text/html; charset=utf-8".equals (contentType.toLowerCase ());
-    }
-
-    public void no_updates_parameter () throws IOException {
-        HttpResponse response = get (ENDPOINT + "/update");
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        Map<?, ?> resultsMap = GSON.fromJson (content, Map.class);
-        assert resultsMap.containsKey ("id") && resultsMap.containsKey ("randomNumber");
-    }
-
-    public void empty_updates_parameter () throws IOException {
-        checkDbRequest ("/update?queries", 1);
-    }
-
-    public void text_updates_parameter () throws IOException {
-        checkDbRequest ("/update?queries=text", 1);
-    }
-
-    public void zero_updates () throws IOException {
-        checkDbRequest ("/update?queries=0", 1);
-    }
-
-    public void one_thousand_updates () throws IOException {
-        checkDbRequest ("/update?queries=1000", 500);
-    }
-
-    public void one_update () throws IOException {
-        checkDbRequest ("/update?queries=1", 1);
-    }
-
-    public void ten_updates () throws IOException {
-        checkDbRequest ("/update?queries=10", 10);
-    }
-
-    public void one_hundred_updates () throws IOException {
-        checkDbRequest ("/update?queries=100", 100);
-    }
-
-    public void five_hundred_updates () throws IOException {
-        checkDbRequest ("/update?queries=500", 500);
-    }
-
-    private void checkDbRequest (String path, int itemsCount) throws IOException {
-        HttpResponse response = get (ENDPOINT + path);
-        String content = getContent (response);
-
-        checkResponse (response, content, "application/json");
-        checkResultItems (content, itemsCount);
-    }
-
-    private HttpResponse get (String uri) throws IOException {
-        return Get (uri).execute ().returnResponse ();
-    }
-
-    private String getContent (HttpResponse response) throws IOException {
-        InputStream in = response.getEntity ().getContent ();
-        return new Scanner (in).useDelimiter ("\\A").next ();
-    }
-
-    private void checkResponse (HttpResponse res, String content, String contentType) {
-        assert res.getFirstHeader ("Server") != null;
-        assert res.getFirstHeader ("Date") != null;
-        assert content.length () == res.getEntity ().getContentLength ();
-        assert res.getEntity ().getContentType ().getValue ().contains (contentType);
-    }
-
-    private void checkResultItems (String result, int size) {
-        List<?> resultsList = GSON.fromJson (result, List.class);
-        assert size == resultsList.size ();
-
-        for (int ii = 0; ii < size; ii++) {
-            Map<?, ?> r = (Map)resultsList.get (ii);
-            assert r.containsKey ("id") && r.containsKey ("randomNumber");
-        }
-    }
-}

+ 0 - 5
frameworks/Java/sabina/undertow-mongodb.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-
-fw_depends java maven
-
-./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mongodb

+ 0 - 5
frameworks/Java/sabina/undertow.sh

@@ -1,5 +0,0 @@
-#!/bin/bash
-
-fw_depends java maven
-
-./setup.sh -Dsabina.backend=undertow -Dsabina.benchmark.repository=mysql

+ 1 - 0
frameworks/Java/wicket/setup.sh

@@ -3,6 +3,7 @@
 fw_depends java resin maven
 fw_depends java resin maven
 
 
 sed -i 's|127.0.0.1|'${DBHOST}'|g' src/main/webapp/WEB-INF/resin-web.xml
 sed -i 's|127.0.0.1|'${DBHOST}'|g' src/main/webapp/WEB-INF/resin-web.xml
+sed -i 's|localhost|'${DBHOST}'|g' src/main/java/hellowicket/WicketApplication.java
 
 
 mvn clean compile war:war
 mvn clean compile war:war
 rm -rf $RESIN_HOME/webapps/*
 rm -rf $RESIN_HOME/webapps/*

+ 4 - 4
frameworks/Java/wildfly-ee7/pom.xml

@@ -10,10 +10,10 @@
 	<properties>
 	<properties>
 		<database.host>localhost</database.host>
 		<database.host>localhost</database.host>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<version.compiler.plugin>3.1</version.compiler.plugin>
-		<version.war.plugin>2.4</version.war.plugin>
-		<version.wildfly>10.0.0.Final</version.wildfly>
-		<version.mysql.connector>5.1.38</version.mysql.connector>
+		<version.compiler.plugin>3.5.1</version.compiler.plugin>
+		<version.war.plugin>2.6</version.war.plugin>
+		<version.wildfly>10.1.0.Final</version.wildfly>
+		<version.mysql.connector>5.1.39</version.mysql.connector>
 		<version.javaee.api>7.0</version.javaee.api>
 		<version.javaee.api>7.0</version.javaee.api>
 		<version.jboss.spec.javaee.7.0>1.0.3.Final</version.jboss.spec.javaee.7.0>
 		<version.jboss.spec.javaee.7.0>1.0.3.Final</version.jboss.spec.javaee.7.0>
 	</properties>
 	</properties>

+ 2 - 2
frameworks/Java/wildfly-ee7/setup.sh

@@ -2,7 +2,7 @@
 
 
 fw_depends java maven
 fw_depends java maven
 
 
-export JAVA_OPTS="-Djava.net.preferIPv4Stack=true -Xms2g -Xmx2g -XX:MaxPermSize=256m -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -verbosegc -Xloggc:/tmp/wildfly_gc.log"
+export JAVA_OPTS="-Djava.net.preferIPv4Stack=true -Xms2g -Xmx2g -XX:+UseG1GC -XX:MaxGCPauseMillis=50 -verbosegc -Xloggc:/tmp/wildfly_gc.log"
 
 
 mvn clean initialize package -Pbenchmark -Ddatabase.host=${DBHOST}
 mvn clean initialize package -Pbenchmark -Ddatabase.host=${DBHOST}
-target/wildfly-10.0.0.Final/bin/standalone.sh -b 0.0.0.0 &
+target/wildfly-10.1.0.Final/bin/standalone.sh -b 0.0.0.0 &

+ 1 - 0
frameworks/JavaScript/nodejs/setup.sh

@@ -7,6 +7,7 @@ sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/mongoose.js
 sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/mysql-raw.js
 sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/mysql-raw.js
 sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/redis.js
 sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/redis.js
 sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/sequelize.js
 sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/sequelize.js
+sed -i 's|127.0.0.1|'"${DBHOST}"'|g' handlers/sequelize-postgres.js
 
 
 npm install
 npm install
 node app.js &
 node app.js &

+ 0 - 2
frameworks/Perl/kelp/benchmark_config.json

@@ -7,7 +7,6 @@
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/queries?queries=",
       "query_url": "/queries?queries=",
       "fortune_url": "/fortunes",
       "fortune_url": "/fortunes",
-      "update_url": "/update?queries=",
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
@@ -30,7 +29,6 @@
       "db_url": "/db",
       "db_url": "/db",
       "query_url": "/queries/mongo?queries=",
       "query_url": "/queries/mongo?queries=",
       "fortune_url": "/fortunes/mongo",
       "fortune_url": "/fortunes/mongo",
-      "update_url": "/update/mongo?queries=",
       "plaintext_url": "/plaintext",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",

+ 32 - 29
frameworks/Python/web2py/README.md

@@ -1,45 +1,48 @@
-# web2py Benchmark Test 
+# [web2py](http://www.web2py.com/) Benchmarking Test
 
 
-Main controller found [here](web2py/applications/app/controllers/default.py)
+This is the web2py portion of a [benchmarking tests suite](../../)
+comparing a variety of web development platforms.
 
 
-Database model found [here](web2py/applications/app/models/db.py)
+The information below is specific to web2py. For further guidance,
+review the [documentation](http://frameworkbenchmarks.readthedocs.org/en/latest/).
+Also note that there is additional information provided in
+the [Python README](../).
 
 
-Fortunes template found [here](web2py/applications/app/views/default/fortune.html)
+There are two sets of web2py tests, "web2py-standard" (the default) and "web2py-optimized". The former set is implemented via standard web2py production code. The latter involves several special optimizations that would not be typical of a web2py application but could be implemented in cases where performance is critical.
 
 
-## Description
+## Web Server and Database Client Software
 
 
-web2py framework (http://www.web2py.com/)
+* [Meinheld](http://meinheld.org/) 0.5.9
+* [Gunicorn](http://gunicorn.org/) 19.4.5
+* [greenlet](http://greenlet.readthedocs.io/en/latest/) 0.4.9
+* [MySQLdb](https://mysqlclient.readthedocs.io/en/latest/) 1.3.7
 
 
-### Database
+## Test Paths
 
 
-MySQL
+"web2py-standard" and "web2py-optimized" tests are accessed via the "/standard" and "/optimized" paths, respectively.
 
 
-### Server
+* JSON Serialization: "/standard/json", "/optimized/json"
+* Single Database Query: "/standard/db", "/optimized/db"
+* Multiple Database Queries: "/standard/dbs?queries=#", "/optimized/dbs?queries=#"*
+* Fortunes: "/standard/fortunes", "/optimized/fortunes"
+* Database Updates: "/standard/update?queries=#", "/optimized/update?queries=#"*
+* Plaintext: "/standard/plaintext", "/optimized/plaintext"
 
 
-* Rocket (default web2py server)
+*Replace # with an actual number.
 
 
-## Test URLs
-### JSON Encoding
+## Source Code
 
 
-http://localhost:8080/json
+* [Database connection and models](app/standard/modules/database.py)
+* [Controller](app/standard/modules/controller.py)
+* [Fortunes template](app/standard/views/fortune.html)
 
 
-### Plaintext
+## Get Help
 
 
-http://localhost:8080/plaintext
+### [Community](http://web2py.com/init/default/documentation)
 
 
-### DB
+* [web2py-users Google Group](https://groups.google.com/forum/#!forum/web2py)
+* [web2py-developers Google Group](https://groups.google.com/forum/#!forum/web2py-developers)
 
 
-http://localhost:8080/db
-
-### Query
-
-http://localhost:8080/queries?queries=2
-
-### Update
-
-http://localhost:8080/updates?queries=2
-
-### Fortune
-
-http://localhost:8080/fortune
+### [Resources](http://web2py.com/init/default/documentation)
 
 
+* [*web2py: Complete Reference Manual*](http://web2py.com/book)

+ 0 - 2
frameworks/Python/web2py/app/app/ABOUT

@@ -1,2 +0,0 @@
-Write something about this app.
-Developed with web2py.

+ 0 - 4
frameworks/Python/web2py/app/app/LICENSE

@@ -1,4 +0,0 @@
-The web2py welcome app is licensed under public domain 
-(except for the css and js files that it includes, which have their own third party licenses).
-
-You can modify this license when you add your own code.

+ 0 - 76
frameworks/Python/web2py/app/app/controllers/default.py

@@ -1,76 +0,0 @@
-# -*- coding: utf-8 -*-
-from random import randint
-from functools import partial
-import json as jsonOut
-
-def getQueryNum(queryString):
-    try:
-        num_queries = int(queryString)
-        if num_queries < 1:
-            return 1
-        if num_queries > 500:
-            return 500
-        return num_queries
-    except ValueError:
-         return 1
-
-def serializeWorld(world):
-    return {
-        "id" : world.id,
-        "randomNumber" : world.randomNumber
-    }
-
-def serializeFortune(fortune):
-    return {
-        "id" : fortune.id,
-        "message": fortune.message
-    }
-
-def plaintext():
-    session.forget()
-    response.headers["Content-Type"]="text/plain; charset=UTF-8"
-    return "Hello, World!"
-
-def json():
-    session.forget()
-    response.headers["Content-Type"]="application/json; charset=UTF-8"
-    return jsonOut.dumps({"message":"Hello, World!"})
-
-def db():
-    session.forget()
-    response.headers["Content-Type"]="application/json; charset=UTF-8"
-    wid = randint(1, 10000)
-    world = DATABASE.world[wid]
-    return jsonOut.dumps(serializeWorld(world))
-
-def queries():
-    session.forget()
-    response.headers["Content-Type"]="application/json; charset=UTF-8"
-    num_queries = getQueryNum(request.vars["queries"])
-    rp = partial(randint, 1, 10000)
-    worlds = [serializeWorld(DATABASE.world[rp()]) for _ in xrange(num_queries)]
-    return jsonOut.dumps(worlds)
-
-def updates():
-    session.forget()
-    response.headers["Content-Type"]="application/json; charset=UTF-8"
-    num_queries = getQueryNum(request.vars["queries"])
-    worlds = []
-    rp = partial(randint, 1, 10000)
-    ids = [rp() for _ in xrange(num_queries)]
-    ids.sort() # To avoid deadlock
-    for id in ids:
-        world = DATABASE.world[id]
-        newNumber = rp()
-        DATABASE(DATABASE.world.id==id).update(randomNumber=newNumber)
-        world.randomNumber = newNumber
-        worlds.append(serializeWorld(world))
-    return jsonOut.dumps(worlds)
-
-def fortune():
-    session.forget()
-    fortunes = DATABASE(DATABASE.fortune).select()
-    fortune_list = fortunes.as_list();
-    fortune_list.append({"id":0, "message":"Additional fortune added at request time."})
-    fortune_list = sorted(fortune_list, key=lambda k: k["message"])
-    return dict(fortunes=fortune_list)

+ 0 - 41
frameworks/Python/web2py/app/app/models/db.py

@@ -1,41 +0,0 @@
-# -*- coding: utf-8 -*-
-
-#########################################################################
-## This scaffolding model makes your app work on Google App Engine too
-## File is released under public domain and you can use without limitations
-#########################################################################
-
-## if SSL/HTTPS is properly configured and you want all HTTP requests to
-## be redirected to HTTPS, uncomment the line below:
-# request.requires_https()
-
-## app configuration made easy. Look inside private/appconfig.ini
-from gluon.contrib.appconfig import AppConfig
-## once in production, remove reload=True to gain full speed
-myconf = AppConfig(reload=False)
-
-DATABASE = None
-DATABASE_URI = "mysql://benchmarkdbuser:[email protected]:3306/hello_world"
-
-db = DAL(DATABASE_URI, fake_migrate_all=False, migrate_enabled=False, pool_size=8, lazy_tables=True)
-DATABASE = db
-## store sessions and tickets there
-##session.connect(request, response, db=db)
-## or store session in Memcache, Redis, etc.
-## from gluon.contrib.memdb import MEMDB
-## from google.appengine.api.memcache import Client
-## session.connect(request, response, db = MEMDB(Client()))
-
-## by default give a view/generic.extension to all actions from localhost
-## none otherwise. a pattern can be 'controller/function.extension'
-response.generic_patterns = [] 
-
-db.define_table("world",
-    Field("id"),
-    Field("randomNumber")
-)
-
-db.define_table("fortune",
-    Field("id"),
-    Field("message")
-)

+ 0 - 19
frameworks/Python/web2py/app/app/private/appconfig.ini

@@ -1,19 +0,0 @@
-; App configuration
-
-; db configuration
-[db]
-uri       = sqlite://storage.sqlite
-migrate   = 1
-pool_size = 1
-
-; smtp address and credentials
-[smtp]
-server = smtp.gmail.com:587
-sender = [email protected]
-login  = username:password
-
-
-; form styling
-[forms]
-formstyle = bootstrap3_inline
-separator = 

+ 0 - 38
frameworks/Python/web2py/app/app/routes.example.py

@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-
-#  This is an app-specific example router
-#
-#  This simple router is used for setting languages from app/languages directory
-#  as a part of the application path:  app/<lang>/controller/function
-#  Language from default.py or 'en' (if the file is not found) is used as
-#  a default_language
-#
-# See <web2py-root-dir>/router.example.py for parameter's detail
-#-------------------------------------------------------------------------------------
-# To enable this route file you must do the steps:
-#
-# 1. rename <web2py-root-dir>/router.example.py to routes.py
-# 2. rename this APP/routes.example.py to APP/routes.py
-#    (where APP - is your application directory)
-# 3. restart web2py (or reload routes in web2py admin interfase)
-#
-# YOU CAN COPY THIS FILE TO ANY APPLICATION'S ROOT DIRECTORY WITHOUT CHANGES!
-
-from fileutils import abspath
-from languages import read_possible_languages
-
-possible_languages = read_possible_languages(abspath('applications', app))
-#NOTE! app - is an application based router's parameter with name of an
-#            application. E.g.'welcome'
-
-routers = {
-    app: dict(
-        default_language = possible_languages['default'][0],
-        languages = [lang for lang in possible_languages
-                           if lang != 'default']
-    )
-}
-
-#NOTE! To change language in your application using these rules add this line
-#in one of your models files:
-#   if request.uri_language: T.force(request.uri_language)

+ 0 - 52
frameworks/Python/web2py/app/app/views/default/index.html

@@ -1,52 +0,0 @@
-{{left_sidebar_enabled,right_sidebar_enabled=False,('message' in globals())}}
-{{extend 'layout.html'}}
-
-{{block header}}
-    <header class="container-fluid background">
-      <div class="jumbotron text-center">
-        {{if response.title:}}
-        <h1>{{=response.title}}
-          <small>{{=response.subtitle or ''}}</small></h1>
-        {{pass}}
-      </div>
-    </header>
-{{end}}
-
-{{if 'message' in globals():}}
-<h2>{{=message}}</h2>
-<p class="lead">{{=T('How did you get here?')}}</p>
-<ol>
-  <li>{{=T('You are successfully running web2py')}}</li>
-  <li>{{=XML(T('You visited the url %s', A(request.env.path_info,_href=request.env.path_info)))}}</li>
-  <li>{{=XML(T('Which called the function %s located in the file %s',
-    (A(request.function+'()',_href='#'),
-    A('web2py/applications/%(application)s/controllers/%(controller)s.py' % request,
-    _href=URL('admin','default','peek', args=(request.application,'controllers',request.controller+'.py'))))))}}</li>
-  <li>{{=XML(T('The output of the file is a dictionary that was rendered by the view %s',
-    A('web2py/applications/%(application)s/views/%(controller)s/index.html' % request,
-    _href=URL('admin','default','peek',args=(request.application,'views',request.controller,'index.html')))))}}</li>
-  <li>{{=T('You can modify this application and adapt it to your needs')}}</li>
-</ol>
-{{elif 'content' in globals():}}
-{{=content}}
-{{else:}}
-{{=BEAUTIFY(response._vars)}}
-{{pass}}
-
-{{block right_sidebar}}
-<div class="panel panel-info">
-  <div class="panel-heading"><h3 class="panel-title"><a class="btn-block"
-      href="{{=URL('admin','default','index')}}">
-      <i class="glyphicon glyphicon-cog"></i>
-      {{=T("admin")}}
-    </a></h3></div>
-  <div class="panel-body">
-    {{=T("Don't know what to do?")}}
-  </div>
-  <ul class="list-group">
-    <li class="list-group-item">{{=A(T("Online examples"), _href=URL('examples','default','index'))}}</li>
-    <li class="list-group-item"><a href="http://web2py.com">web2py.com</a></li>
-    <li class="list-group-item"><a href="http://web2py.com/book">{{=T('Documentation')}}</a></li>
-  </ul>
-</div>
-{{end}}

+ 0 - 35
frameworks/Python/web2py/app/app/views/default/user.html

@@ -1,35 +0,0 @@
-{{extend 'layout.html'}}
-
-<h2>
-{{=T('Sign Up') if request.args(0) == 'register' else T('Log In') if request.args(0) == 'login' else T(request.args(0).replace('_',' ').title())}}
-</h2>
-
-<div class="container">
-    <div class="row">
-        <div id="web2py_user_form" class="col-lg-6">
-        {{
-        if request.args(0)=='login':
-            if not 'register' in auth.settings.actions_disabled:
-                form.add_button(T('Sign Up'),URL(args='register', vars={'_next': request.vars._next} if request.vars._next else None),_class='btn btn-default')
-            pass
-            if not 'request_reset_password' in auth.settings.actions_disabled:
-                form.add_button(T('Lost Password'),URL(args='request_reset_password'),_class='btn btn-default')
-            pass
-        pass
-        =form
-        }}
-        </div>
-    </div>
-</div>
-
-
-{{block page_js}}
-<script>
-    jQuery("#web2py_user_form input:visible:enabled:first").focus();
-{{if request.args(0)=='register':}}
-    web2py_validate_entropy(jQuery('#auth_user_password'),100);
-{{elif request.args(0)=='change_password':}}
-    web2py_validate_entropy(jQuery('#no_table_new_password'),100);
-{{pass}}
-</script>
-{{end page_js}}

+ 0 - 16
frameworks/Python/web2py/app/app/views/generic.html

@@ -1,16 +0,0 @@
-{{extend 'layout.html'}}
-{{"""
-
-You should not modify this file. 
-It is used as default when a view is not provided for your controllers
-
-"""}}
-<h2>{{=' '.join(x.capitalize() for x in request.function.split('_'))}}</h2>
-{{if len(response._vars)==1:}}
-{{=BEAUTIFY(response._vars.values()[0])}}
-{{elif len(response._vars)>1:}}
-{{=BEAUTIFY(response._vars)}}
-{{pass}}
-{{if request.is_local:}}
-{{=response.toolbar()}}
-{{pass}}

+ 0 - 0
frameworks/Python/web2py/app/app/__init__.py → frameworks/Python/web2py/app/optimized/__init__.py


+ 9 - 0
frameworks/Python/web2py/app/optimized/models/app.py

@@ -0,0 +1,9 @@
+# -*- coding: utf-8 -*-
+from gluon import current
+# Re-use the controller from the "standard" application.
+from applications.standard.modules import controller
+
+current.optimized = True # Flag used in controller.py to trigger DAL optimizations.
+
+# To avoid the overhead of executing a controller, the response is returned here.
+raise HTTP(200, getattr(controller, request.function)(), **current.response.headers)

+ 0 - 0
frameworks/Python/web2py/app/app/views/__init__.py → frameworks/Python/web2py/app/optimized/views/__init__.py


+ 3 - 5
frameworks/Python/web2py/app/app/views/default/fortune.html → frameworks/Python/web2py/app/optimized/views/fortune.html

@@ -6,10 +6,8 @@
   <body>
   <body>
     <table><tr><th>id</th><th>message</th></tr>
     <table><tr><th>id</th><th>message</th></tr>
     {{for fortune in fortunes:}}
     {{for fortune in fortunes:}}
-      <tr><td>{{=fortune["id"]}}</td><td>{{=fortune["message"]}}</td></tr>
-      {{pass}}
-      </table>
+      <tr><td>{{=fortune['id']}}</td><td>{{=fortune['message']}}</td></tr>
+    {{pass}}
+    </table>
   </body>
   </body>
 </html>
 </html>
-
-

+ 6 - 13
frameworks/Python/web2py/app/routes.py

@@ -1,14 +1,7 @@
-routers = dict(
-    BASE = dict(
-        default_application='app',
-    )
-)
+# -*- coding: utf-8 -*-
 
 
-routes_in = (
-	("/json", "/app/default/json"),
-	("/plaintext", "/app/default/plaintext"),
-        ("/db", "/app/default/db"),
-	("/queries", "/app/default/queries"),
-	("/updates", "/app/default/updates"),
-	("/fortune", "/app/default/fortune")
-)
+routes_in = [
+    ('/standard/$anything', '/standard/default/index/$anything'),
+    # Disable sessions on the /optimized route for additional speed-up.
+    ('/optimized/$anything', '/optimized/default/$anything', dict(web2py_disable_session=True))
+]

+ 1 - 0
frameworks/Python/web2py/app/standard/__init__.py

@@ -0,0 +1 @@
+

+ 15 - 0
frameworks/Python/web2py/app/standard/controllers/default.py

@@ -0,0 +1,15 @@
+# -*- coding: utf-8 -*-
+
+# Controller functions would typically be defined in this file but are instead
+# imported from a module to enable sharing with the "optimized" application.
+import controller
+from gluon import current
+
+current.optimized = False # Flag used in controller.py to trigger DAL optimizations.
+
+session.forget(response) # For speed-up when sessions are not needed.
+
+def index():
+    # The first URL arg specifies the controller function to be executed
+    # from the controller.py module.
+    return getattr(controller, request.args(0))()

+ 1 - 0
frameworks/Python/web2py/app/standard/modules/__init__.py

@@ -0,0 +1 @@
+

+ 51 - 0
frameworks/Python/web2py/app/standard/modules/controller.py

@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+from random import randint
+from functools import partial
+import json as jsonOut
+
+from gluon import current
+from database import Dal, RawDal, num_queries
+
+def plaintext():
+    current.response.headers['Content-Type'] = 'text/plain'
+    return 'Hello, World!'
+
+def json():
+    current.response.headers['Content-Type'] = 'application/json'
+    return jsonOut.dumps({'message': 'Hello, World!'})
+
+def db():
+    current.response.headers['Content-Type']='application/json'
+    return jsonOut.dumps(Dal('World').get_world(randint(1, 10000)))
+
+def queries():
+    current.response.headers['Content-Type']='application/json'
+    db = RawDal() if current.optimized else Dal('World')
+    get_world = db.get_world
+    r10k = partial(randint, 1, 10000)
+    worlds = [get_world(r10k()) for _ in
+              xrange(num_queries(current.request.vars.queries))]
+    return jsonOut.dumps(worlds)
+
+def updates():
+    current.response.headers['Content-Type']='application/json'
+    db = RawDal() if current.optimized else Dal('World')
+    get_world = db.get_world
+    update_world = db.update_world
+    r10k = partial(randint, 1, 10000)
+    worlds = []
+    for wid in (r10k() for _ in xrange(num_queries(current.request.vars.queries))):
+        world = get_world(wid)
+        newNumber = r10k()
+        world['randomNumber'] = newNumber
+        worlds.append(world)
+        update_world(wid, newNumber)
+    if current.optimized:
+        db.flush_world_updates() # Batch updates.
+    return jsonOut.dumps(worlds)
+
+def fortune():
+    new_message = {'id': 0, 'message': 'Additional fortune added at request time.'}
+    db = RawDal() if current.optimized else Dal('Fortune')
+    fortunes = db.get_fortunes(new_message=new_message)
+    return current.response.render('fortune.html', fortunes=fortunes)

+ 59 - 0
frameworks/Python/web2py/app/standard/modules/database.py

@@ -0,0 +1,59 @@
+# -*- coding: utf-8 -*-
+import os
+from operator import itemgetter
+from gluon.storage import Storage
+from gluon.dal import DAL, Field, Row
+
+DBHOST = os.environ.get('DBHOST', 'localhost')
+DATABASE_URI = 'mysql://benchmarkdbuser:benchmarkdbpass@%s:3306/hello_world' % DBHOST
+
+class Dal(object):
+    def __init__(self, table=None, pool_size=8):
+        self.db = DAL(DATABASE_URI, migrate_enabled=False, pool_size=pool_size)
+        if table == 'World':
+            self.db.define_table('World', Field('randomNumber', 'integer'))
+        elif table == 'Fortune':
+            self.db.define_table('Fortune', Field('message'))
+
+    def get_world(self, wid):
+        # Setting `cacheable=True` improves performance by foregoing the creation
+        # of some non-essential attributes. It does *not* actually cache the
+        # database results (it simply produces a Rows object that *could be* cached).
+        return self.db(self.db.World.id == wid).select(cacheable=True)[0].as_dict()
+
+    def update_world(self, wid, randomNumber):
+        self.db(self.db.World.id == wid).update(randomNumber=randomNumber)
+
+    def get_fortunes(self, new_message):
+        fortunes = self.db(self.db.Fortune).select(cacheable=True)
+        fortunes.records.append(Row(new_message))
+        return fortunes.sort(itemgetter('message'))
+
+class RawDal(Dal):
+    def __init__(self):
+        super(RawDal, self).__init__()
+        self.world_updates = []
+
+    def get_world(self, wid):
+        return self.db.executesql('SELECT * FROM World WHERE id = %s',
+                                  placeholders=[wid], as_dict=True)[0]
+
+    def update_world(self, wid, randomNumber):
+        self.world_updates.extend([randomNumber, wid])
+
+    def flush_world_updates(self):
+        query = ';'.join('UPDATE World SET randomNumber=%s WHERE id=%s'
+                         for _ in xrange(len(self.world_updates) / 2))
+        self.db.executesql(query, placeholders=self.world_updates)
+
+    def get_fortunes(self, new_message):
+        fortunes = self.db.executesql('SELECT * FROM Fortune', as_dict=True)
+        fortunes.append(new_message)
+        return sorted(fortunes, key=itemgetter('message'))
+
+def num_queries(queries):
+    try:
+        num = int(queries)
+        return 1 if num < 1 else 500 if num > 500 else num
+    except ValueError:
+         return 1

+ 1 - 0
frameworks/Python/web2py/app/standard/views/__init__.py

@@ -0,0 +1 @@
+

+ 13 - 0
frameworks/Python/web2py/app/standard/views/fortune.html

@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Fortunes</title>
+  </head>
+  <body>
+    <table><tr><th>id</th><th>message</th></tr>
+    {{for fortune in fortunes:}}
+      <tr><td>{{=fortune['id']}}</td><td>{{=fortune['message']}}</td></tr>
+    {{pass}}
+    </table>
+  </body>
+</html>

+ 15 - 0
frameworks/Python/web2py/app/wsgi.py

@@ -0,0 +1,15 @@
+import sys
+import os
+
+path = os.path.dirname(os.path.abspath(__file__))
+os.chdir(path)
+
+if not os.path.isdir('applications'):
+    raise RuntimeError('Running from the wrong folder')
+
+sys.path = [path] + [p for p in sys.path if not p == path]
+
+sys.stdout = sys.stderr
+
+from gluon.main import wsgibase
+application = wsgibase

+ 35 - 11
frameworks/Python/web2py/benchmark_config.json

@@ -3,25 +3,49 @@
   "tests": [{
   "tests": [{
     "default": {
     "default": {
       "setup_file": "setup",
       "setup_file": "setup",
-      "plaintext_url": "/plaintext",
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/updates?queries=",
+      "plaintext_url": "/standard/plaintext",
+      "json_url": "/standard/json",
+      "db_url": "/standard/db",
+      "query_url": "/standard/queries?queries=",
+      "fortune_url": "/standard/fortune",
+      "update_url": "/standard/updates?queries=",
       "port": 8080,
       "port": 8080,
       "approach": "Realistic",
       "approach": "Realistic",
-      "classification": "Micro",
+      "classification": "Fullstack",
       "database": "MySQL",
       "database": "MySQL",
       "framework": "web2py",
       "framework": "web2py",
       "language": "Python",
       "language": "Python",
       "orm": "Full",
       "orm": "Full",
-      "platform": "web2Py",
+      "platform": "Meinheld",
       "webserver": "None",
       "webserver": "None",
       "os": "Linux",
       "os": "Linux",
       "database_os": "Linux",
       "database_os": "Linux",
-      "display_name": "web2py",
-      "notes": "CPython 2.7"
-    } 
+      "display_name": "web2py-standard",
+      "notes": "CPython 2.7",
+      "versus": "wsgi"
+    },
+    "optimized": {
+      "setup_file": "setup",
+      "plaintext_url": "/optimized/plaintext",
+      "json_url": "/optimized/json",
+      "db_url": "/optimized/db",
+      "query_url": "/optimized/queries?queries=",
+      "fortune_url": "/optimized/fortune",
+      "update_url": "/optimized/updates?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "web2py",
+      "language": "Python",
+      "orm": "Full",
+      "platform": "Meinheld",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "web2py-optimized",
+      "notes": "CPython 2.7",
+      "versus": "wsgi"
+    }
   }]
   }]
 }
 }

+ 12 - 0
frameworks/Python/web2py/compile_apps.py

@@ -0,0 +1,12 @@
+# -*- coding: utf-8 -*-
+import sys
+import os
+
+path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'web2py')
+
+sys.path = [path] + [p for p in sys.path if not p == path]
+
+from gluon.compileapp import compile_application
+
+compile_application(os.path.join(path, 'applications', 'standard'))
+compile_application(os.path.join(path, 'applications', 'optimized'))

+ 22 - 0
frameworks/Python/web2py/gunicorn_conf.py

@@ -0,0 +1,22 @@
+import multiprocessing
+import os
+import sys
+
+_is_travis = os.environ.get('TRAVIS') == 'true'
+
+workers = multiprocessing.cpu_count() * 3
+if _is_travis:
+    workers = 2
+
+bind = "0.0.0.0:8080"
+keepalive = 120
+errorlog = '-'
+pidfile = 'gunicorn.pid'
+pythonpath = 'web2py'
+
+worker_class = "meinheld.gmeinheld.MeinheldWorker"
+
+def post_fork(server, worker):
+    # Disable access log
+    import meinheld.server
+    meinheld.server.set_access_logger(None)

+ 4 - 1
frameworks/Python/web2py/requirements.txt

@@ -1 +1,4 @@
-mysqlclient==1.3.6
+mysqlclient==1.3.7
+gunicorn==19.4.5
+meinheld==0.5.9
+greenlet==0.4.9

+ 13 - 5
frameworks/Python/web2py/setup.sh

@@ -2,13 +2,21 @@
 
 
 fw_depends python2
 fw_depends python2
 
 
-sed -i 's|127.0.0.1|'${DBHOST}'|g' app/app/models/db.py
-
 pip install --install-option="--prefix=${PY2_ROOT}" -r $TROOT/requirements.txt
 pip install --install-option="--prefix=${PY2_ROOT}" -r $TROOT/requirements.txt
 
 
 rm -fr web2py
 rm -fr web2py
-git clone --recursive --branch R-2.10.3 https://github.com/web2py/web2py.git 
-cp -r app/app/ web2py/applications/
+git clone --recursive --branch master https://github.com/web2py/web2py.git
+cd web2py
+# The following commit is checked out in order to take advantage of several
+# bug fixes that were made after the latest stable release. This can be changed
+# in future rounds once a new stable release has been made.
+git checkout 44362aa42948dca08ddf1b2f86ac03c69b0d48e4
+cd ..
+cp -r app/standard/ web2py/applications/
+cp -r app/optimized/ web2py/applications/
+cp app/wsgi.py web2py/
 cp app/routes.py web2py/
 cp app/routes.py web2py/
+touch web2py/__init__.py
+python compile_apps.py
 
 
-python web2py/web2py.py -a '' -i 0.0.0.0 -p 8080  &
+gunicorn web2py.wsgi:application -c gunicorn_conf.py &

+ 0 - 66
frameworks/Ruby/grape/benchmark_config.json

@@ -23,28 +23,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-puma-mri"
       "versus": "rack-puma-mri"
     }, 
     }, 
-    "puma-jruby": {
-      "setup_file": "run_jruby_puma",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/query?queries=", 
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "grape",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Puma",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "grape-puma-jruby",
-      "notes": "",
-      "versus": "rack-puma-jruby"
-    },
     "puma-rbx": {
     "puma-rbx": {
       "setup_file": "run_rbx_puma",
       "setup_file": "run_rbx_puma",
       "json_url": "/json",
       "json_url": "/json",
@@ -89,50 +67,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-thin"
       "versus": "rack-thin"
     },  
     },  
-    "torqbox-jruby": {
-      "setup_file": "run_torqbox",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/query?queries=", 
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "grape",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "TorqBox",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "grape-torqbox-jruby",
-      "notes": "",
-      "versus": "rack-torqbox-jruby"
-    },  
-    "trinidad-jruby": {
-      "setup_file": "run_trinidad",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/query?queries=", 
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "grape",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Trinidad",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "grape-trinidad-jruby",
-      "notes": "",
-      "versus": "rack-trinidad-jruby"
-    },  
     "unicorn": {
     "unicorn": {
       "setup_file": "run_unicorn",
       "setup_file": "run_unicorn",
       "json_url": "/json",
       "json_url": "/json",

+ 0 - 9
frameworks/Ruby/grape/run_jruby_puma.sh

@@ -1,9 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-sed -i 's|  host:.*|  host: '"${DBHOST}"'|g' config/database.yml
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-rvm jruby-$JRUBY_VERSION do bundle exec puma -b tcp://0.0.0.0:8080 -e production &

+ 0 - 9
frameworks/Ruby/grape/run_torqbox.sh

@@ -1,9 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-sed -i 's|  host:.*|  host: '"${DBHOST}"'|g' config/database.yml
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-rvm jruby-$JRUBY_VERSION do bundle exec torqbox -b 0.0.0.0 -E production &

+ 0 - 9
frameworks/Ruby/grape/run_trinidad.sh

@@ -1,9 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-sed -i 's|  host:.*|  host: '"${DBHOST}"'|g' config/database.yml
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-rvm jruby-$JRUBY_VERSION do bundle exec trinidad --config config/trinidad.yml &

+ 0 - 0
frameworks/Ruby/ngx_mruby/__init__.py


+ 0 - 69
frameworks/Ruby/padrino/benchmark_config.json

@@ -24,29 +24,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-puma-mri"
       "versus": "rack-puma-mri"
     },
     },
-    "puma-jruby": {
-      "setup_file": "run_jruby_puma",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/queries?queries=", 
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "padrino",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Puma",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "padrino-jruby",
-      "notes": "",
-      "versus": "rack-puma-jruby"
-    },
     "puma-rbx": {
     "puma-rbx": {
       "setup_file": "run_rbx_puma",
       "setup_file": "run_rbx_puma",
       "json_url": "/json",
       "json_url": "/json",
@@ -70,52 +47,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-puma-rbx"
       "versus": "rack-puma-rbx"
     },
     },
-    "torqbox-jruby": {
-      "setup_file": "run_torqbox",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/queries?queries=", 
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "padrino",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "TorqBox",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "padrino-torqbox-jruby",
-      "notes": "",
-      "versus": "rack-torqbox-jruby"
-    },
-    "trinidad-jruby": {
-      "setup_file": "run_trinidad",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/queries?queries=", 
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "padrino",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Trinidad",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "padrino-trinidad-jruby",
-      "notes": "",
-      "versus": "rack-trinidad-jruby"
-    },
     "thin": {
     "thin": {
       "setup_file": "run_thin",
       "setup_file": "run_thin",
       "json_url": "/json",
       "json_url": "/json",

+ 0 - 7
frameworks/Ruby/padrino/run_jruby_puma.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-DB_HOST=${DBHOST} rvm jruby-$JRUBY_VERSION do bundle exec puma -C config/puma.rb &

+ 0 - 7
frameworks/Ruby/padrino/run_torqbox.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-DB_HOST=${DBHOST} rvm jruby-$JRUBY_VERSION do bundle exec torqbox -b 0.0.0.0 -E production &

+ 0 - 7
frameworks/Ruby/padrino/run_trinidad.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-DB_HOST=${DBHOST} rvm jruby-$JRUBY_VERSION do bundle exec trinidad --config config/trinidad.yml &

+ 0 - 63
frameworks/Ruby/rack/benchmark_config.json

@@ -22,27 +22,6 @@
       "display_name": "rack-puma-mri",
       "display_name": "rack-puma-mri",
       "notes": ""
       "notes": ""
     },
     },
-    "puma-jruby": {
-      "setup_file": "run_jruby_puma",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/queries?queries=", 
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Stripped",
-      "classification": "Platform",
-      "database": "MySQL",
-      "framework": "rack",
-      "language": "Ruby",
-      "orm": "Raw",
-      "platform": "JRuby",
-      "webserver": "Puma",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "rack-puma-jruby",
-      "notes": ""
-    },
     "puma-rbx": {
     "puma-rbx": {
       "setup_file": "run_rbx_puma",
       "setup_file": "run_rbx_puma",
       "json_url": "/json",
       "json_url": "/json",
@@ -85,48 +64,6 @@
       "display_name": "rack-thin",
       "display_name": "rack-thin",
       "notes": ""
       "notes": ""
     },
     },
-    "torqbox-jruby": {
-      "setup_file": "run_torqbox",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/queries?queries=", 
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Stripped",
-      "classification": "Platform",
-      "database": "MySQL",
-      "framework": "rack",
-      "language": "Ruby",
-      "orm": "Raw",
-      "platform": "JRuby",
-      "webserver": "TorqBox",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "rack-torqbox-jruby",
-      "notes": ""
-    },
-    "trinidad-jruby": {
-      "setup_file": "run_trinidad",
-      "json_url": "/json",
-      "db_url": "/db", 
-      "query_url": "/queries?queries=", 
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Stripped",
-      "classification": "Platform",
-      "database": "MySQL",
-      "framework": "rack",
-      "language": "Ruby",
-      "orm": "Raw",
-      "platform": "JRuby",
-      "webserver": "Trinidad",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "rack-trinidad-jruby",
-      "notes": ""
-    },
     "unicorn": {
     "unicorn": {
       "setup_file": "run_unicorn",
       "setup_file": "run_unicorn",
       "json_url": "/json",
       "json_url": "/json",

+ 0 - 9
frameworks/Ruby/rack/run_jruby_puma.sh

@@ -1,9 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-sed -i 's|127.0.0.1|'${DBHOST}'|g' config/database.yml
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-rvm jruby-$JRUBY_VERSION do bundle exec puma -b tcp://0.0.0.0:8080 -e production &

+ 0 - 20
frameworks/Ruby/rails-stripped/benchmark_config.json

@@ -20,26 +20,6 @@
       "display_name": "rails-ruby",
       "display_name": "rails-ruby",
       "notes": "",
       "notes": "",
       "versus": "rack-unicorn"
       "versus": "rack-unicorn"
-    },
-    "jruby": {
-      "setup_file": "setup_jruby",
-      "json_url": "/hello_world/json",
-      "db_url": "/hello_world/db",
-      "query_url": "/hello_world/db?queries=",
-      "port": 8080,
-      "approach": "Stripped",
-      "classification": "Fullstack",
-      "database": "MySQL",
-      "framework": "rails",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "TorqBox",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "rails-jruby",
-      "notes": "",
-      "versus": "rack-torqbox-jruby"
     }
     }
   }]
   }]
 }
 }

+ 0 - 69
frameworks/Ruby/rails/benchmark_config.json

@@ -24,29 +24,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-puma-mri"
       "versus": "rack-puma-mri"
     },
     },
-    "puma-jruby": {
-      "setup_file": "run_jruby_puma",
-      "json_url": "/hello_world/json",
-      "db_url": "/hello_world/db",
-      "query_url": "/hello_world/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Fullstack",
-      "database": "MySQL",
-      "framework": "rails",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Puma",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "rails-puma-jruby",
-      "notes": "",
-      "versus": "rack-puma-jruby"
-    },
     "puma-rbx": {
     "puma-rbx": {
       "setup_file": "run_rbx_puma",
       "setup_file": "run_rbx_puma",
       "json_url": "/hello_world/json",
       "json_url": "/hello_world/json",
@@ -93,52 +70,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-thin"
       "versus": "rack-thin"
     },
     },
-    "torqbox-jruby": {
-      "setup_file": "run_torqbox",
-      "json_url": "/hello_world/json",
-      "db_url": "/hello_world/db",
-      "query_url": "/hello_world/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Fullstack",
-      "database": "MySQL",
-      "framework": "rails",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "TorqBox",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "rails-torqbox-jruby",
-      "notes": "",
-      "versus": "rack-torqbox-jruby"
-    },
-    "trinidad-jruby": {
-      "setup_file": "run_trinidad",
-      "json_url": "/hello_world/json",
-      "db_url": "/hello_world/db",
-      "query_url": "/hello_world/query?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Fullstack",
-      "database": "MySQL",
-      "framework": "rails",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Trinidad",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "rails-trinidad-jruby",
-      "notes": "",
-      "versus": "rack-trinidad-jruby"
-    },
     "unicorn": {
     "unicorn": {
       "setup_file": "run_unicorn",
       "setup_file": "run_unicorn",
       "json_url": "/hello_world/json",
       "json_url": "/hello_world/json",

+ 0 - 7
frameworks/Ruby/rails/run_jruby_puma.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-DB_HOST=${DBHOST} rvm jruby-$JRUBY_VERSION do bundle exec puma -b tcp://0.0.0.0:8080 -e production &

+ 0 - 7
frameworks/Ruby/rails/run_torqbox.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-DB_HOST=${DBHOST} rvm jruby-$JRUBY_VERSION do bundle exec torqbox -b 0.0.0.0 -E production &

+ 0 - 7
frameworks/Ruby/rails/run_trinidad.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-DB_HOST=${DBHOST} rvm jruby-$JRUBY_VERSION do bundle exec trinidad --config config/trinidad.yml &

+ 0 - 23
frameworks/Ruby/sinatra-sequel/benchmark_config.json

@@ -24,29 +24,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-puma-mri"
       "versus": "rack-puma-mri"
     },
     },
-    "puma-jruby": {
-      "setup_file": "run_jruby_puma",
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=",
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "sinatra-sequel",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Puma",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "sinatra-sequel-puma-jruby",
-      "notes": "",
-      "versus": "rack-puma-jruby"
-    },
     "puma-rbx": {
     "puma-rbx": {
       "setup_file": "run_rbx_puma",
       "setup_file": "run_rbx_puma",
       "json_url": "/json",
       "json_url": "/json",

+ 0 - 12
frameworks/Ruby/sinatra-sequel/run_jruby_puma.sh

@@ -1,12 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-9k
-
-rvm jruby-$JRUBY_VERSION do \
-  bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-MAX_THREADS=256 ; export MAX_THREADS
-MIN_THREADS=$(( MAX_THREADS / 8 * 2 ))
-
-rvm jruby-$JRUBY_VERSION do \
-  bundle exec puma -t $MIN_THREADS:$MAX_THREADS -b tcp://0.0.0.0:8080 -e production &

+ 0 - 69
frameworks/Ruby/sinatra/benchmark_config.json

@@ -24,29 +24,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-puma-mri"
       "versus": "rack-puma-mri"
     },
     },
-    "puma-jruby": {
-      "setup_file": "run_jruby_puma",
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "sinatra",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Puma",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "sinatra-puma-jruby",
-      "notes": "",
-      "versus": "rack-puma-jruby"
-    },
     "puma-rbx": {
     "puma-rbx": {
       "setup_file": "run_rbx_puma",
       "setup_file": "run_rbx_puma",
       "json_url": "/json",
       "json_url": "/json",
@@ -93,52 +70,6 @@
       "notes": "",
       "notes": "",
       "versus": "rack-thin"
       "versus": "rack-thin"
     },
     },
-    "torqbox-jruby": {
-      "setup_file": "run_torqbox",
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "sinatra",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "TorqBox",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "sinatra-torqbox-jruby",
-      "notes": "",
-      "versus": "rack-torqbox-jruby"
-    },
-    "trinidad-jruby": {
-      "setup_file": "run_trinidad",
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortunes",
-      "update_url": "/updates?queries=", 
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Micro",
-      "database": "MySQL",
-      "framework": "sinatra",
-      "language": "Ruby",
-      "orm": "Full",
-      "platform": "JRuby",
-      "webserver": "Trinidad",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "sinatra-trinidad-jruby",
-      "notes": "",
-      "versus": "rack-trinidad-jruby"
-    },
     "unicorn": {
     "unicorn": {
       "setup_file": "run_unicorn",
       "setup_file": "run_unicorn",
       "json_url": "/json",
       "json_url": "/json",

+ 0 - 7
frameworks/Ruby/sinatra/run_jruby_puma.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends rvm jruby-1.7
-
-rvm jruby-$JRUBY_VERSION do bundle install --jobs=4 --gemfile=$TROOT/Gemfile --path=vendor/bundle
-
-WEB_SERVER=Puma DB_HOST=${DBHOST} rvm jruby-$JRUBY_VERSION do bundle exec puma -C config/puma.rb &

+ 2 - 2
frameworks/Scala/fintrospect/README.md

@@ -4,8 +4,8 @@
 The tests were run with:
 The tests were run with:
 
 
 * [Java Oracle 1.8.0_25](http://www.oracle.com/technetwork/java/javase)
 * [Java Oracle 1.8.0_25](http://www.oracle.com/technetwork/java/javase)
-* [fintrospect 12.4.0](https://github.com/daviddenton/fintrospect)
-* [finagle 6.33.0](https://github.com/twitter/finagle)
+* [fintrospect 13.5.2](https://github.com/daviddenton/fintrospect)
+* [finagle 6.36.0](https://github.com/twitter/finagle)
 
 
 ## Test URLs
 ## Test URLs
 
 

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

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

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