Browse Source

Merge pull request #2 from TechEmpower/master

Merging base branch
Sanjoy Dey 9 years ago
parent
commit
5468f3d8cb
100 changed files with 1560 additions and 1152 deletions
  1. 4 8
      .travis.yml
  2. 14 6
      config/php.ini
  3. 50 4
      frameworks/C++/treefrog/benchmark_config.json
  4. 20 18
      frameworks/C++/treefrog/config/application.ini
  5. 3 3
      frameworks/C++/treefrog/config/mongodb.ini
  6. 1 1
      frameworks/C++/treefrog/controllers/controllers.pro
  7. 18 0
      frameworks/C++/treefrog/controllers/fortunecontroller.cpp
  8. 2 1
      frameworks/C++/treefrog/controllers/fortunecontroller.h
  9. 51 1
      frameworks/C++/treefrog/controllers/worldcontroller.cpp
  10. 7 0
      frameworks/C++/treefrog/controllers/worldcontroller.h
  11. 1 1
      frameworks/C++/treefrog/helpers/helpers.pro
  12. 104 0
      frameworks/C++/treefrog/models/mngfortune.cpp
  13. 51 0
      frameworks/C++/treefrog/models/mngfortune.h
  14. 105 0
      frameworks/C++/treefrog/models/mngworld.cpp
  15. 51 0
      frameworks/C++/treefrog/models/mngworld.h
  16. 9 3
      frameworks/C++/treefrog/models/models.pro
  17. 35 0
      frameworks/C++/treefrog/models/mongoobjects/mngfortuneobject.h
  18. 35 0
      frameworks/C++/treefrog/models/mongoobjects/mngworldobject.h
  19. 20 0
      frameworks/C++/treefrog/setup-mongodb.sh
  20. 20 0
      frameworks/C++/treefrog/setup-postgres.sh
  21. 5 4
      frameworks/C++/treefrog/setup-thread.sh
  22. 4 3
      frameworks/C++/treefrog/setup.sh
  23. 1 1
      frameworks/C++/treefrog/views/_src/_src.pro
  24. 1 0
      frameworks/C++/treefrog/views/fortune/.trim_mode
  25. 1 2
      frameworks/C++/treefrog/views/fortune/index.erb
  26. 22 0
      frameworks/C++/treefrog/views/fortune/mindex.erb
  27. 1 0
      frameworks/C++/treefrog/views/world/.trim_mode
  28. 3 1
      frameworks/CSharp/revenj/README.md
  29. 4 2
      frameworks/CSharp/revenj/Revenj.Bench/Context.cs
  30. 18 0
      frameworks/CSharp/revenj/Revenj.Bench/FortuneTemplate.cs
  31. 391 0
      frameworks/CSharp/revenj/Revenj.Bench/Fortunes.cs
  32. 14 0
      frameworks/CSharp/revenj/Revenj.Bench/Fortunes.tt
  33. 29 9
      frameworks/CSharp/revenj/Revenj.Bench/RestService.cs
  34. 14 0
      frameworks/CSharp/revenj/Revenj.Bench/Revenj.Bench.csproj
  35. 5 1
      frameworks/CSharp/revenj/Revenj.Bench/model.dsl
  36. 2 0
      frameworks/CSharp/revenj/benchmark_config.json
  37. 1 1
      frameworks/CSharp/revenj/install.sh
  38. 6 17
      frameworks/CSharp/revenj/setup.ps1
  39. 7 14
      frameworks/CSharp/revenj/setup.sh
  40. 3 1
      frameworks/CSharp/revenj/source_code
  41. 0 5
      frameworks/Crystal/moonshine/.gitignore
  42. 0 5
      frameworks/Crystal/moonshine/README.md
  43. 0 28
      frameworks/Crystal/moonshine/benchmark_config.json
  44. 0 157
      frameworks/Crystal/moonshine/server-postgres.cr
  45. 0 158
      frameworks/Crystal/moonshine/server-redis.cr
  46. 0 7
      frameworks/Crystal/moonshine/setup-postgres.sh
  47. 0 7
      frameworks/Crystal/moonshine/setup-redis.sh
  48. 0 15
      frameworks/Crystal/moonshine/shard.yml
  49. 0 2
      frameworks/Go/fasthttp-mysql/.gitignore
  50. 0 51
      frameworks/Go/fasthttp-mysql/benchmark_config.json
  51. 0 3
      frameworks/Go/fasthttp-mysql/setup.bat
  52. 0 14
      frameworks/Go/fasthttp-mysql/setup.sh
  53. 0 14
      frameworks/Go/fasthttp-mysql/setup_prefork.sh
  54. 0 4
      frameworks/Go/fasthttp-mysql/source_code
  55. 0 22
      frameworks/Go/fasthttp-mysql/src/templates/fortune.qtpl
  56. 0 2
      frameworks/Go/fasthttp-postgresql/.gitignore
  57. 0 16
      frameworks/Go/fasthttp-postgresql/README.md
  58. 0 51
      frameworks/Go/fasthttp-postgresql/benchmark_config.json
  59. 0 3
      frameworks/Go/fasthttp-postgresql/setup.bat
  60. 0 14
      frameworks/Go/fasthttp-postgresql/setup.sh
  61. 0 14
      frameworks/Go/fasthttp-postgresql/setup_prefork.sh
  62. 0 4
      frameworks/Go/fasthttp-postgresql/source_code
  63. 1 1
      frameworks/Go/fasthttp/README.md
  64. 97 0
      frameworks/Go/fasthttp/benchmark_config.json
  65. 14 0
      frameworks/Go/fasthttp/setup-mysql-prefork.sh
  66. 14 0
      frameworks/Go/fasthttp/setup-mysql.sh
  67. 14 0
      frameworks/Go/fasthttp/setup-postgresql-prefork.sh
  68. 14 0
      frameworks/Go/fasthttp/setup-postgresql.sh
  69. 3 0
      frameworks/Go/fasthttp/setup.bat
  70. 8 0
      frameworks/Go/fasthttp/source_code
  71. 123 0
      frameworks/Go/fasthttp/src/common/common.go
  72. 18 137
      frameworks/Go/fasthttp/src/server-mysql/server.go
  73. 21 145
      frameworks/Go/fasthttp/src/server-postgresql/server.go
  74. 3 0
      frameworks/Go/fasthttp/src/templates/aux.go
  75. 0 0
      frameworks/Go/fasthttp/src/templates/fortune.qtpl
  76. 0 3
      frameworks/Go/go-std-mongodb/README.md
  77. 0 28
      frameworks/Go/go-std-mongodb/benchmark_config.json
  78. 0 6
      frameworks/Go/go-std-mongodb/source_code
  79. 0 14
      frameworks/Go/go-std-mongodb/templates/fortune.html
  80. 0 9
      frameworks/Go/go-std-mongodb/templates/layout.html
  81. 0 2
      frameworks/Go/go-std-mysql/setup.bat
  82. 0 7
      frameworks/Go/go-std-mysql/setup.sh
  83. 0 7
      frameworks/Go/go-std-mysql/setup_prefork.sh
  84. 0 3
      frameworks/Go/go-std-mysql/source_code
  85. 0 26
      frameworks/Go/go-std-postgresql/benchmark_config.json
  86. 0 7
      frameworks/Go/go-std-postgresql/setup.sh
  87. 0 3
      frameworks/Go/go-std-postgresql/source_code
  88. 2 2
      frameworks/Go/go-std/README.md
  89. 45 3
      frameworks/Go/go-std/benchmark_config.json
  90. 24 21
      frameworks/Go/go-std/hello_mongo.go
  91. 0 0
      frameworks/Go/go-std/hello_mysql.go
  92. 0 0
      frameworks/Go/go-std/hello_postgres.go
  93. 0 0
      frameworks/Go/go-std/setup.bat
  94. 7 0
      frameworks/Go/go-std/setup.sh
  95. 2 3
      frameworks/Go/go-std/setup_mongo.sh
  96. 7 0
      frameworks/Go/go-std/setup_postgres.sh
  97. 7 0
      frameworks/Go/go-std/setup_prefork.sh
  98. 3 0
      frameworks/Go/go-std/source_code
  99. 0 1
      frameworks/Go/revel-jet/.gitignore
  100. 0 26
      frameworks/Go/revel-jet/benchmark_config.json

+ 4 - 8
.travis.yml

@@ -40,7 +40,6 @@ env:
     - "TESTDIR=Clojure/pedestal"
     - "TESTDIR=Clojure/aleph"
     - "TESTDIR=Crystal/crystal-raw"
-    - "TESTDIR=Crystal/moonshine"
     - "TESTDIR=Crystal/kemal"
     - "TESTDIR=D/vibed"
     - "TESTDIR=Dart/dart-raw"
@@ -56,16 +55,11 @@ env:
     - "TESTDIR=Erlang/misultin"
     - "TESTDIR=Go/beego"
     - "TESTDIR=Go/falcore"
-    - "TESTDIR=Go/fasthttp-mysql"
-    - "TESTDIR=Go/fasthttp-postgresql"
+    - "TESTDIR=Go/fasthttp"
     - "TESTDIR=Go/gin"
     - "TESTDIR=Go/goji"
-    - "TESTDIR=Go/go-std-mongodb"
-    - "TESTDIR=Go/go-std-mysql"
-    - "TESTDIR=Go/go-std-postgresql"
+    - "TESTDIR=Go/go-std"
     - "TESTDIR=Go/revel"
-    - "TESTDIR=Go/revel-jet"
-    - "TESTDIR=Go/revel-qbs"
     - "TESTDIR=Go/webgo"
     - "TESTDIR=Groovy/grails"
     - "TESTDIR=Haskell/snap"
@@ -85,6 +79,7 @@ env:
     - "TESTDIR=Java/jawn"
     - "TESTDIR=Java/jetty-servlet"
     - "TESTDIR=Java/jetty"
+    - "TESTDIR=Java/jlhttp"
     - "TESTDIR=Java/jooby"
     - "TESTDIR=Java/netty"
     - "TESTDIR=Java/ninja-standalone"
@@ -185,6 +180,7 @@ env:
     - "TESTDIR=Scala/akka-http"
     - "TESTDIR=Scala/colossus"
     - "TESTDIR=Scala/finagle"
+    - "TESTDIR=Scala/finatra"
     - "TESTDIR=Scala/fintrospect"
     - "TESTDIR=Scala/lift-stateless"
     - "TESTDIR=Scala/plain"

+ 14 - 6
config/php.ini

@@ -372,7 +372,7 @@ zend.enable_gc = On
 ; threat in any way, but it makes it possible to determine whether you use PHP
 ; on your server or not.
 ; http://php.net/expose-php
-expose_php = On
+expose_php = Off
 
 ;;;;;;;;;;;;;;;;;;;
 ; Resource Limits ;
@@ -868,9 +868,10 @@ default_socket_timeout = 60
 ;extension=apc.so
 zend_extension=opcache.so
 extension=redis.so
-extension=phalcon.so
+;extension=phalcon.so
 ;extension=yaf.so
 extension=mongodb.so
+extension=mongo.so
 ;extension=php_bz2.dll
 ;extension=php_curl.dll
 ;extension=php_fileinfo.dll
@@ -1865,10 +1866,17 @@ ldap.max_links = -1
 ; Local Variables:
 ; tab-width: 4
 ; End:
-[apc]
-apc.stat = 0
-apc.enable_cli = 1
-apc.shm_size = 64M
+;[apc]
+;apc.stat = 0
+;apc.enable_cli = 1
+;apc.shm_size = 64M
+
+[opcache]
+opcache.validate_timestamps = 0 ; The same that apc.stat = 0
+;opcache.enable_file_override = 1 ; Faster for some frameworks
+;opcache.save_comments = 0 ; Breaks any fw using annotations comments
+;opcache.fast_shutdown = 1 ; Have problems with some big frameworks
+
 
 [yaf]
 yaf.library =

+ 50 - 4
frameworks/C++/treefrog/benchmark_config.json

@@ -2,6 +2,29 @@
   "framework": "treefrog",
   "tests": [{
     "default": {
+      "setup_file": "setup-thread",
+      "json_url": "/json/json",
+      "db_url": "/world/random",
+      "query_url": "/world/queries/",
+      "fortune_url": "/fortune/index",
+      "update_url": "/world/updates/",
+      "plaintext_url": "/world/plain",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MySQL",
+      "framework": "treefrog",
+      "language": "C++",
+      "orm": "Micro",
+      "platform": "Treefrog",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "treefrog-thread",
+      "notes": "",
+      "versus": ""
+    },
+    "hybrid": {
       "setup_file": "setup",
       "json_url": "/json/json",
       "db_url": "/world/random",
@@ -24,8 +47,8 @@
       "notes": "",
       "versus": ""
     },
-    "thread": {
-      "setup_file": "setup-thread",
+    "postgres": {
+      "setup_file": "setup-postgres",
       "json_url": "/json/json",
       "db_url": "/world/random",
       "query_url": "/world/queries/",
@@ -35,7 +58,7 @@
       "port": 8080,
       "approach": "Realistic",
       "classification": "Fullstack",
-      "database": "MySQL",
+      "database": "Postgres",
       "framework": "treefrog",
       "language": "C++",
       "orm": "Micro",
@@ -43,7 +66,30 @@
       "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "treefrog-thread",
+      "display_name": "treefrog-postgres",
+      "notes": "",
+      "versus": ""
+    },
+    "mongodb": {
+      "setup_file": "setup-mongodb",
+      "json_url": "/json/json",
+      "db_url": "/world/mrandom",
+      "query_url": "/world/mqueries/",
+      "fortune_url": "/fortune/mindex",
+      "update_url": "/world/mupdates/",
+      "plaintext_url": "/world/plain",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "MongoDB",
+      "framework": "treefrog",
+      "language": "C++",
+      "orm": "Micro",
+      "platform": "Treefrog",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "treefrog-mongo",
       "notes": "",
       "versus": ""
     }

+ 20 - 18
frameworks/C++/treefrog/config/application.ini

@@ -14,10 +14,6 @@ InternalEncoding=UTF-8
 # specified encoding. See QTextCodec class reference.
 HttpOutputEncoding=UTF-8
 
-# Sets the charset parameter of 'text/html' in the HTTP Content-Type
-# header to the specified string.
-HtmlContentCharset=UTF-8
-
 # Sets a language/country pair, such as en_US, ja_JP, etc.
 # If this value is empty, the system's locale is used.
 Locale=
@@ -33,7 +29,7 @@ UploadTemporaryDirectory=tmp
 SqlDatabaseSettingsFiles=database.ini
 
 # Specify the setting file for MongoDB.
-MongoDbSettingsFile=
+MongoDbSettingsFile=mongodb.ini
 
 # Specify the directory path to store SQL query files
 SqlQueriesStoredDirectory=sql/
@@ -64,6 +60,25 @@ LimitRequestBody=0
 # forgery never work; otherwise it's enabled.
 EnableCsrfProtectionModule=false
 
+# Enables HTTP method override if true. The following are priorities of
+# override.
+#  - Value of query parameter named '_method'
+#  - Value of X-HTTP-Method-Override header
+#  - Value of X-HTTP-Method header
+#  - Value of X-METHOD-OVERRIDE header
+EnableHttpMethodOverride=false
+
+# Sets the timeout in seconds during which a keep-alive HTTP connection
+# will stay open on the server side. The zero value disables keep-alive
+# client connections.
+HttpKeepAliveTimeout=10
+
+# Forces some libraries to be loaded before all others. It means to set
+# the LD_PRELOAD environment variable for the application server, Linux
+# only. The paths to shared objects, jemalloc or TCMalloc, can be
+# specified.
+LDPreload=/usr/lib/x86_64-linux-gnu/libjemalloc.so
+
 ##
 ## Session section
 ##
@@ -112,19 +127,6 @@ MPM.thread.MaxAppServers=10
 # per server process.
 MPM.thread.MaxThreadsPerAppServer=100
 
-##
-## MPM Prefork section
-##
-
-# Maximum number of server processes allowed to start
-MPM.prefork.MaxServers=20
-
-# Minimum number of server processes allowed to start
-MPM.prefork.MinServers=5
-
-# Number of server processes which are kept spare
-MPM.prefork.SpareServers=5
-
 ##
 ## MPM Hybrid section
 ##

+ 3 - 3
frameworks/C++/treefrog/config/mongodb.ini

@@ -3,7 +3,7 @@
 #
 
 [dev]
-DatabaseName=mdb
+DatabaseName=hello_world
 HostName=localhost
 Port=
 UserName=
@@ -19,8 +19,8 @@ Password=
 ConnectOptions=
 
 [product]
-DatabaseName=
-HostName=
+DatabaseName=hello_world
+HostName=localhost
 Port=
 UserName=
 Password=

+ 1 - 1
frameworks/C++/treefrog/controllers/controllers.pro

@@ -1,7 +1,7 @@
 TARGET = controller
 TEMPLATE = lib
 CONFIG += shared x86_64 c++11
-QT += network sql xml
+QT += network sql xml qml
 QT -= gui
 DEFINES += TF_DLL
 DESTDIR = ../lib

+ 18 - 0
frameworks/C++/treefrog/controllers/fortunecontroller.cpp

@@ -1,11 +1,17 @@
 #include "fortunecontroller.h"
 #include "fortune.h"
+#include "mngfortune.h"
 
 static bool caseSensitiveLessThan(const Fortune &f1, const Fortune &f2)
 {
     return f1.message() < f2.message();
 }
 
+static bool caseSensitiveMngFortuneLessThan(const MngFortune &f1, const MngFortune &f2)
+{
+    return f1.message() < f2.message();
+}
+
 FortuneController::FortuneController(const FortuneController &)
     : ApplicationController()
 { }
@@ -22,6 +28,18 @@ void FortuneController::index()
     render();
 }
 
+void FortuneController::mindex()
+{
+    QList<MngFortune> fortuneList = MngFortune::getAll();
+    MngFortune fortune;
+    fortune.setMessage(QLatin1String("Additional fortune added at request time."));
+    fortuneList << fortune;
+    // Sort
+    qSort(fortuneList.begin(), fortuneList.end(), caseSensitiveMngFortuneLessThan);
+    texport(fortuneList);
+    render("mindex");
+}
+
 void FortuneController::show(const QString &pk)
 {
     Fortune fortune = Fortune::get(pk.toUInt());

+ 2 - 1
frameworks/C++/treefrog/controllers/fortunecontroller.h

@@ -14,7 +14,8 @@ public:
     bool transactionEnabled() const { return false; }
 
 public slots:
-    void index();
+    void index();   // SQL
+    void mindex();  // MongoDB
     void show(const QString &pk);
     void entry();
     void create();

+ 51 - 1
frameworks/C++/treefrog/controllers/worldcontroller.cpp

@@ -1,5 +1,6 @@
 #include "worldcontroller.h"
 #include "world.h"
+#include "mngworld.h"
 
 
 WorldController::WorldController(const WorldController &)
@@ -139,7 +140,7 @@ void WorldController::updates(const QString &num)
         world = World::get(id);
         world.setRandomNumber( Tf::random(9999) + 1 );
         world.update();
-	worlds << world.toVariantMap();
+        worlds << world.toVariantMap();
     }
     renderJson(worlds);
 }
@@ -156,5 +157,54 @@ void WorldController::remove(const QString &pk)
 }
 
 
+
+/*
+  MongoDB
+ */
+void WorldController::mqueries()
+{
+    mqueries("1");
+}
+
+void WorldController::mqueries(const QString &num)
+{
+    QVariantList worlds;
+    int d = qMin(qMax(num.toInt(), 1), 500);
+
+    for (int i = 0; i < d; ++i) {
+        QString id = QString::number(Tf::random(9999) + 1);
+        worlds << MngWorld::get(id).toVariantMap();
+    }
+    renderJson(worlds);
+}
+
+void WorldController::mrandom()
+{
+    int id = Tf::random(9999) + 1;
+    World world = World::get(id);
+    renderJson(world.toVariantMap());
+}
+
+void WorldController::mupdates()
+{
+    mupdates("1");
+}
+
+void WorldController::mupdates(const QString &num)
+{
+    QVariantList worlds;
+    int d = qMin(qMax(num.toInt(), 1), 500);
+    MngWorld world;
+
+    for (int i = 0; i < d; ++i) {
+        QString id = QString::number(Tf::random(9999) + 1);
+        world = MngWorld::get(id);
+        world.setRandomNumber( Tf::random(9999) + 1 );
+        world.update();
+        worlds << world.toVariantMap();
+    }
+    renderJson(worlds);
+}
+
 // Don't remove below this line
 T_REGISTER_CONTROLLER(worldcontroller)

+ 7 - 0
frameworks/C++/treefrog/controllers/worldcontroller.h

@@ -28,6 +28,13 @@ public slots:
     void updates();
     void remove(const QString &pk);
 
+    // MongoDB
+    void mqueries();
+    void mqueries(const QString &num);
+    void mrandom();
+    void mupdates(const QString &num);
+    void mupdates();
+
 private:
     void renderEntry(const QVariantMap &world = QVariantMap());
     void renderEdit(const QVariantMap &world = QVariantMap());

+ 1 - 1
frameworks/C++/treefrog/helpers/helpers.pro

@@ -2,7 +2,7 @@ TARGET = helper
 TEMPLATE = lib
 CONFIG += shared x86_64 c++11
 QT  -= gui
-QT  += 
+QT  += qml
 DEFINES += TF_DLL
 DESTDIR = ../lib
 DEPENDPATH +=

+ 104 - 0
frameworks/C++/treefrog/models/mngfortune.cpp

@@ -0,0 +1,104 @@
+#include <TreeFrogModel>
+#include "mngfortune.h"
+#include "mngfortuneobject.h"
+
+MngFortune::MngFortune()
+    : TAbstractModel(), d(new MngFortuneObject)
+{
+    d->id = 0;
+}
+
+MngFortune::MngFortune(const MngFortune &other)
+    : TAbstractModel(), d(new MngFortuneObject(*other.d))
+{ }
+
+MngFortune::MngFortune(const MngFortuneObject &object)
+    : TAbstractModel(), d(new MngFortuneObject(object))
+{ }
+
+MngFortune::~MngFortune()
+{
+    // If the reference count becomes 0,
+    // the shared data object 'MngFortuneObject' is deleted.
+}
+
+int MngFortune::id() const
+{
+    return d->id;
+}
+
+QString MngFortune::message() const
+{
+    return d->message;
+}
+
+void MngFortune::setMessage(const QString &message)
+{
+    d->message = message;
+}
+
+MngFortune &MngFortune::operator=(const MngFortune &other)
+{
+    d = other.d;  // increments the reference count of the data
+    return *this;
+}
+
+MngFortune MngFortune::create(const QString &message)
+{
+    MngFortuneObject obj;
+    obj.message = message;
+    if (!obj.create()) {
+        return MngFortune();
+    }
+    return MngFortune(obj);
+}
+
+MngFortune MngFortune::create(const QVariantMap &values)
+{
+    MngFortune model;
+    model.setProperties(values);
+    if (!model.d->create()) {
+        model.d->clear();
+    }
+    return model;
+}
+
+MngFortune MngFortune::get(const QString &id)
+{
+    TMongoODMapper<MngFortuneObject> mapper;
+    return MngFortune(mapper.findByObjectId(id));
+}
+
+int MngFortune::count()
+{
+    TMongoODMapper<MngFortuneObject> mapper;
+    return mapper.findCount();
+}
+
+QList<MngFortune> MngFortune::getAll()
+{
+    return tfGetModelListByMongoCriteria<MngFortune, MngFortuneObject>(TCriteria());
+}
+
+QJsonArray MngFortune::getAllJson()
+{
+    QJsonArray array;
+    TMongoODMapper<MngFortuneObject> mapper;
+
+    if (mapper.find()) {
+        while (mapper.next()) {
+            array.append(QJsonValue(QJsonObject::fromVariantMap(MngFortune(mapper.value()).toVariantMap())));
+        }
+    }
+    return array;
+}
+
+TModelObject *MngFortune::modelData()
+{
+    return d.data();
+}
+
+const TModelObject *MngFortune::modelData() const
+{
+    return d.data();
+}

+ 51 - 0
frameworks/C++/treefrog/models/mngfortune.h

@@ -0,0 +1,51 @@
+#ifndef MNGFORTUNE_H
+#define MNGFORTUNE_H
+
+#include <QStringList>
+#include <QDateTime>
+#include <QVariant>
+#include <QSharedDataPointer>
+#include <TGlobal>
+#include <TAbstractModel>
+
+class TModelObject;
+class MngFortuneObject;
+class QJsonArray;
+
+
+class T_MODEL_EXPORT MngFortune : public TAbstractModel
+{
+public:
+    MngFortune();
+    MngFortune(const MngFortune &other);
+    MngFortune(const MngFortuneObject &object);
+    ~MngFortune();
+
+    int id() const;
+    QString message() const;
+    void setMessage(const QString &message);
+    MngFortune &operator=(const MngFortune &other);
+
+    bool create() { return TAbstractModel::create(); }
+    bool update() { return TAbstractModel::update(); }
+    bool save()   { return TAbstractModel::save(); }
+    bool remove() { return TAbstractModel::remove(); }
+
+    static MngFortune create(const QString &message);
+    static MngFortune create(const QVariantMap &values);
+    static MngFortune get(const QString &id);
+    static int count();
+    static QList<MngFortune> getAll();
+    static QJsonArray getAllJson();
+
+private:
+    QSharedDataPointer<MngFortuneObject> d;
+
+    TModelObject *modelData();
+    const TModelObject *modelData() const;
+};
+
+Q_DECLARE_METATYPE(MngFortune)
+Q_DECLARE_METATYPE(QList<MngFortune>)
+
+#endif // MNGFORTUNE_H

+ 105 - 0
frameworks/C++/treefrog/models/mngworld.cpp

@@ -0,0 +1,105 @@
+#include <TreeFrogModel>
+#include "mngworld.h"
+#include "mngworldobject.h"
+
+MngWorld::MngWorld()
+    : TAbstractModel(), d(new MngWorldObject)
+{
+    d->id = 0;
+    d->randomNumber = 0;
+}
+
+MngWorld::MngWorld(const MngWorld &other)
+    : TAbstractModel(), d(new MngWorldObject(*other.d))
+{ }
+
+MngWorld::MngWorld(const MngWorldObject &object)
+    : TAbstractModel(), d(new MngWorldObject(object))
+{ }
+
+MngWorld::~MngWorld()
+{
+    // If the reference count becomes 0,
+    // the shared data object 'MngWorldObject' is deleted.
+}
+
+int MngWorld::id() const
+{
+    return d->id;
+}
+
+int MngWorld::randomNumber() const
+{
+    return d->randomNumber;
+}
+
+void MngWorld::setRandomNumber(int randomNumber)
+{
+    d->randomNumber = randomNumber;
+}
+
+MngWorld &MngWorld::operator=(const MngWorld &other)
+{
+    d = other.d;  // increments the reference count of the data
+    return *this;
+}
+
+MngWorld MngWorld::create(int randomNumber)
+{
+    MngWorldObject obj;
+    obj.randomNumber = randomNumber;
+    if (!obj.create()) {
+        return MngWorld();
+    }
+    return MngWorld(obj);
+}
+
+MngWorld MngWorld::create(const QVariantMap &values)
+{
+    MngWorld model;
+    model.setProperties(values);
+    if (!model.d->create()) {
+        model.d->clear();
+    }
+    return model;
+}
+
+MngWorld MngWorld::get(const QString &id)
+{
+    TMongoODMapper<MngWorldObject> mapper;
+    return MngWorld(mapper.findByObjectId(id));
+}
+
+int MngWorld::count()
+{
+    TMongoODMapper<MngWorldObject> mapper;
+    return mapper.findCount();
+}
+
+QList<MngWorld> MngWorld::getAll()
+{
+    return tfGetModelListByMongoCriteria<MngWorld, MngWorldObject>(TCriteria());
+}
+
+QJsonArray MngWorld::getAllJson()
+{
+    QJsonArray array;
+    TMongoODMapper<MngWorldObject> mapper;
+
+    if (mapper.find()) {
+        while (mapper.next()) {
+            array.append(QJsonValue(QJsonObject::fromVariantMap(MngWorld(mapper.value()).toVariantMap())));
+        }
+    }
+    return array;
+}
+
+TModelObject *MngWorld::modelData()
+{
+    return d.data();
+}
+
+const TModelObject *MngWorld::modelData() const
+{
+    return d.data();
+}

+ 51 - 0
frameworks/C++/treefrog/models/mngworld.h

@@ -0,0 +1,51 @@
+#ifndef MNGWORLD_H
+#define MNGWORLD_H
+
+#include <QStringList>
+#include <QDateTime>
+#include <QVariant>
+#include <QSharedDataPointer>
+#include <TGlobal>
+#include <TAbstractModel>
+
+class TModelObject;
+class MngWorldObject;
+class QJsonArray;
+
+
+class T_MODEL_EXPORT MngWorld : public TAbstractModel
+{
+public:
+    MngWorld();
+    MngWorld(const MngWorld &other);
+    MngWorld(const MngWorldObject &object);
+    ~MngWorld();
+
+    int id() const;
+    int randomNumber() const;
+    void setRandomNumber(int randomNumber);
+    MngWorld &operator=(const MngWorld &other);
+
+    bool create() { return TAbstractModel::create(); }
+    bool update() { return TAbstractModel::update(); }
+    bool save()   { return TAbstractModel::save(); }
+    bool remove() { return TAbstractModel::remove(); }
+
+    static MngWorld create(int randomNumber);
+    static MngWorld create(const QVariantMap &values);
+    static MngWorld get(const QString &id);
+    static int count();
+    static QList<MngWorld> getAll();
+    static QJsonArray getAllJson();
+
+private:
+    QSharedDataPointer<MngWorldObject> d;
+
+    TModelObject *modelData();
+    const TModelObject *modelData() const;
+};
+
+Q_DECLARE_METATYPE(MngWorld)
+Q_DECLARE_METATYPE(QList<MngWorld>)
+
+#endif // MNGWORLD_H

+ 9 - 3
frameworks/C++/treefrog/models/models.pro

@@ -1,12 +1,12 @@
 TARGET = model
 TEMPLATE = lib
 CONFIG += shared x86_64 c++11
-QT += sql
+QT += sql qml
 QT -= gui
 DEFINES += TF_DLL
 DESTDIR = ../lib
-INCLUDEPATH += ../helpers sqlobjects
-DEPENDPATH  += ../helpers sqlobjects
+INCLUDEPATH += ../helpers sqlobjects mongoobjects
+DEPENDPATH  += ../helpers sqlobjects mongoobjects
 LIBS += -L../lib -lhelper
 
 include(../appbase.pri)
@@ -17,3 +17,9 @@ SOURCES += fortune.cpp
 HEADERS += sqlobjects/worldobject.h
 HEADERS += world.h
 SOURCES += world.cpp
+HEADERS += mongoobjects/mngworldobject.h
+HEADERS += mngworld.h
+SOURCES += mngworld.cpp
+HEADERS += mongoobjects/mngfortuneobject.h
+HEADERS += mngfortune.h
+SOURCES += mngfortune.cpp

+ 35 - 0
frameworks/C++/treefrog/models/mongoobjects/mngfortuneobject.h

@@ -0,0 +1,35 @@
+#ifndef MNGFORTUNEOBJECT_H
+#define MNGFORTUNEOBJECT_H
+
+#include <TMongoObject>
+#include <QSharedData>
+
+
+class T_MODEL_EXPORT MngFortuneObject : public TMongoObject, public QSharedData
+{
+public:
+    QString _id;
+    int id;
+    QString message;
+
+    enum PropertyIndex {
+        _Id = 0,
+        Id,
+        Message,
+    };
+
+    virtual QString collectionName() const { return "fortune"; }
+    virtual QString objectId() const { return _id; }
+    virtual QString &objectId() { return _id; }
+
+private:
+    Q_OBJECT
+    Q_PROPERTY(QString _id READ get_id WRITE set_id)
+    T_DEFINE_PROPERTY(QString, _id)
+    Q_PROPERTY(int id READ getid WRITE setid)
+    T_DEFINE_PROPERTY(int, id)
+    Q_PROPERTY(QString message READ getmessage WRITE setmessage)
+    T_DEFINE_PROPERTY(QString, message)
+};
+
+#endif // MNGFORTUNEOBJECT_H

+ 35 - 0
frameworks/C++/treefrog/models/mongoobjects/mngworldobject.h

@@ -0,0 +1,35 @@
+#ifndef MNGWORLDOBJECT_H
+#define MNGWORLDOBJECT_H
+
+#include <TMongoObject>
+#include <QSharedData>
+
+
+class T_MODEL_EXPORT MngWorldObject : public TMongoObject, public QSharedData
+{
+public:
+    QString _id;
+    int id;
+    int randomNumber;
+
+    enum PropertyIndex {
+        _Id = 0,
+        Id,
+        RandomNumber,
+    };
+
+    virtual QString collectionName() const { return "world"; }
+    virtual QString objectId() const { return _id; }
+    virtual QString &objectId() { return _id; }
+
+private:
+    Q_OBJECT
+    Q_PROPERTY(QString _id READ get_id WRITE set_id)
+    T_DEFINE_PROPERTY(QString, _id)
+    Q_PROPERTY(int id READ getid WRITE setid)
+    T_DEFINE_PROPERTY(int, id)
+    Q_PROPERTY(int randomNumber READ getrandomNumber WRITE setrandomNumber)
+    T_DEFINE_PROPERTY(int, randomNumber)
+};
+
+#endif // MNGWORLDOBJECT_H

+ 20 - 0
frameworks/C++/treefrog/setup-mongodb.sh

@@ -0,0 +1,20 @@
+#!/bin/bash
+
+sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/database.ini
+sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/mongodb.ini
+sed -i 's|DriverType=.*|DriverType=QMYSQL|g' config/database.ini
+sed -i 's|MultiProcessingModule=.*|MultiProcessingModule=thread|g' config/application.ini
+
+fw_depends treefrog
+
+# 1. Generate Makefile
+qmake -r CONFIG+=release
+
+# 2. Compile applicaton
+make
+
+# 3. Clean log files
+rm -f log/*.log
+
+# 4. Start TreeFrog
+treefrog -d $TROOT

+ 20 - 0
frameworks/C++/treefrog/setup-postgres.sh

@@ -0,0 +1,20 @@
+#!/bin/bash
+
+sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/database.ini
+sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/mongodb.ini
+sed -i 's|DriverType=.*|DriverType=QPSQL|g' config/database.ini
+sed -i 's|MultiProcessingModule=.*|MultiProcessingModule=thread|g' config/application.ini
+
+fw_depends treefrog
+
+# 1. Generate Makefile
+qmake -r CONFIG+=release
+
+# 2. Compile applicaton
+make
+
+# 3. Clean log files
+rm -f log/*.log
+
+# 4. Start TreeFrog
+treefrog -d $TROOT

+ 5 - 4
frameworks/C++/treefrog/setup-thread.sh

@@ -1,7 +1,9 @@
 #!/bin/bash
 
 sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/database.ini
-sed -i "s|MultiProcessingModule=.*|MultiProcessingModule=thread|g" config/application.ini
+sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/mongodb.ini
+sed -i 's|DriverType=.*|DriverType=QMYSQL|g' config/database.ini
+sed -i 's|MultiProcessingModule=.*|MultiProcessingModule=thread|g' config/application.ini
 
 fw_depends treefrog
 
@@ -9,11 +11,10 @@ fw_depends treefrog
 qmake -r CONFIG+=release
 
 # 2. Compile applicaton
-make clean
-make -j8
+make
 
 # 3. Clean log files
 rm -f log/*.log
 
 # 4. Start TreeFrog
-treefrog -d $TROOT &
+treefrog -d $TROOT

+ 4 - 3
frameworks/C++/treefrog/setup.sh

@@ -1,7 +1,9 @@
 #!/bin/bash
 
 sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/database.ini
-sed -i "s|MultiProcessingModule=.*|MultiProcessingModule=hybrid|g" config/application.ini
+sed -i 's|HostName=.*|HostName='"$DBHOST"'|g' config/mongodb.ini
+sed -i 's|DriverType=.*|DriverType=QMYSQL|g' config/database.ini
+sed -i 's|MultiProcessingModule=.*|MultiProcessingModule=hybrid|g' config/application.ini
 
 fw_depends treefrog
 
@@ -9,8 +11,7 @@ fw_depends treefrog
 qmake -r CONFIG+=release
 
 # 2. Compile applicaton
-make clean
-make -j8
+make
 
 # 3. Clean log files
 rm -f log/*.log

+ 1 - 1
frameworks/C++/treefrog/views/_src/_src.pro

@@ -1,7 +1,7 @@
 TARGET = view
 TEMPLATE = lib
 CONFIG += shared x86_64 c++11
-QT += network xml
+QT += network xml qml
 QT -= gui
 DEFINES += TF_DLL
 INCLUDEPATH += ../../helpers ../../models

+ 1 - 0
frameworks/C++/treefrog/views/fortune/.trim_mode

@@ -0,0 +1 @@
+2

+ 1 - 2
frameworks/C++/treefrog/views/fortune/index.erb

@@ -11,8 +11,7 @@
 <th>message</th>
 </tr>
 <% tfetch(QList<Fortune>, fortuneList); %>
-<% for (QListIterator<Fortune> it(fortuneList); it.hasNext(); ) {
-     const Fortune &i = it.next(); %>
+<% for (auto &i : fortuneList) { %>
 <tr>
 <td><%= i.id() %></td>
 <td><%= i.message() %></td>

+ 22 - 0
frameworks/C++/treefrog/views/fortune/mindex.erb

@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<%#include "mngfortune.h" %>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+<% tfetch(QList<MngFortune>, fortuneList); %>
+<% for (auto &i : fortuneList) { %>
+<tr>
+<td><%= i.id() %></td>
+<td><%= i.message() %></td>
+</tr>
+<% } %>
+</table>
+</body>
+</html>

+ 1 - 0
frameworks/C++/treefrog/views/world/.trim_mode

@@ -0,0 +1 @@
+2

+ 3 - 1
frameworks/CSharp/revenj/README.md

@@ -2,6 +2,7 @@
 
 Revenj HTTP server + DB API + JSON API + PostgreSQL.
 It uses precompiled DSL model for POCO classes.
+It uses T4 Templates for HTML output
 
 ## DSL model
 Data structures are defined in a DSL schema
@@ -19,6 +20,7 @@ Data structures are defined in a DSL schema
  * DB - `http://localhost:8080/bench/db`
  * Queries - `http://localhost:8080/bench/queries/{count}`
  * Updates -  `http://localhost:8080/bench/updates/{count}`
+ * Fortune -  `http://localhost:8080/bench/fortunes`
 
 ## Software Versions
 The tests were run with:
@@ -26,4 +28,4 @@ The tests were run with:
  * [Mono 4.2](http://www.mono-project.com/)
  * [.NET 4.0](https://www.microsoft.com/net)
  * [Postgres 9.3](http://www.postgresql.org/)
- * [Revenj.NET 1.2.1](http://github.com/ngs-doo/revenj)
+ * [Revenj.NET 1.3.1](http://github.com/ngs-doo/revenj)

+ 4 - 2
frameworks/CSharp/revenj/Revenj.Bench/Context.cs

@@ -13,7 +13,8 @@ namespace Revenj.Bench
 	{
 		public readonly ChunkedMemoryStream Stream;
 		public readonly TextWriter Writer;
-		public readonly IPersistableRepository<World> Repository;
+		public readonly IPersistableRepository<World> WorldRepository;
+		public readonly IQueryableRepository<Fortune> FortuneRepository;
 		public readonly IRepositoryBulkReader BulkReader;
 		public readonly Lazy<World>[] LazyWorlds = new Lazy<World>[512];
 		public readonly World[] Worlds = new World[512];
@@ -25,7 +26,8 @@ namespace Revenj.Bench
 			var dqm = service.Resolve<IDatabaseQueryManager>();
 			var factory = service.Resolve<IObjectFactory>().CreateInnerFactory();
 			factory.RegisterInterfaces(dqm.StartQuery(false));
-			Repository = factory.Resolve<IPersistableRepository<World>>();
+			WorldRepository = factory.Resolve<IPersistableRepository<World>>();
+			FortuneRepository = factory.Resolve<IQueryableRepository<Fortune>>();
 			BulkReader = factory.BulkRead(ChunkedMemoryStream.Static());
 		}
 	}

+ 18 - 0
frameworks/CSharp/revenj/Revenj.Bench/FortuneTemplate.cs

@@ -0,0 +1,18 @@
+using System.Collections.Generic;
+using System.IO;
+
+namespace Revenj.Bench
+{
+	public partial class Fortunes
+	{
+		private readonly TextWriter writer;
+
+		public Fortunes(List<KeyValuePair<int, string>> arg, TextWriter writer)
+		{
+			this._fortunesField = arg;
+			this.writer = writer;
+		}
+
+		public new void Write(string what) { writer.Write(what); }
+	}
+}

+ 391 - 0
frameworks/CSharp/revenj/Revenj.Bench/Fortunes.cs

@@ -0,0 +1,391 @@
+// ------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version: 10.0.0.0
+//  
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+// ------------------------------------------------------------------------------
+namespace Revenj.Bench
+{
+    using System;
+    
+    
+    #line 1 "C:\Projects\FrameworkBenchmarks\frameworks\CSharp\revenj\Revenj.Bench\Fortunes.tt"
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "10.0.0.0")]
+    public partial class Fortunes : FortunesBase
+    {
+        public virtual string TransformText()
+        {
+            this.Write("\n");
+            this.Write("\n");
+            this.Write("\n<!DOCTYPE html>\n<html>\n<head><title>Fortunes</title></head>\n<body><table><tr><th" +
+                    ">id</th><th>message</th></tr>\n");
+            
+            #line 1 "C:\Projects\FrameworkBenchmarks\frameworks\CSharp\revenj\Revenj.Bench\Fortunes.tt"
+ for (var i=0; i<fortunes.Count;i++) {
+	var f = fortunes[i]; 
+            
+            #line default
+            #line hidden
+            this.Write("\n<tr><td>");
+            
+            #line 1 "C:\Projects\FrameworkBenchmarks\frameworks\CSharp\revenj\Revenj.Bench\Fortunes.tt"
+ Write(f.Key.ToString()); 
+            
+            #line default
+            #line hidden
+            this.Write("</td><td>");
+            
+            #line 1 "C:\Projects\FrameworkBenchmarks\frameworks\CSharp\revenj\Revenj.Bench\Fortunes.tt"
+ Write(System.Web.HttpUtility.HtmlEncode(f.Value)); 
+            
+            #line default
+            #line hidden
+            this.Write("</td></tr>\n");
+            
+            #line 1 "C:\Projects\FrameworkBenchmarks\frameworks\CSharp\revenj\Revenj.Bench\Fortunes.tt"
+ } 
+            
+            #line default
+            #line hidden
+            this.Write("\n</table>\n</body>\n</html>");
+            return this.GenerationEnvironment.ToString();
+        }
+        
+        #line 1 "C:\Projects\FrameworkBenchmarks\frameworks\CSharp\revenj\Revenj.Bench\Fortunes.tt"
+
+private global::System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>> _fortunesField;
+
+/// <summary>
+/// Access the fortunes parameter of the template.
+/// </summary>
+private global::System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>> fortunes
+{
+    get
+    {
+        return this._fortunesField;
+    }
+}
+
+
+public virtual void Initialize()
+{
+    if ((this.Errors.HasErrors == false))
+    {
+bool fortunesValueAcquired = false;
+if (this.Session.ContainsKey("fortunes"))
+{
+    if ((typeof(global::System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>>).IsAssignableFrom(this.Session["fortunes"].GetType()) == false))
+    {
+        this.Error("The type \'System.Collections.Generic.List<System.Collections.Generic.KeyValuePair" +
+                "<int, string>>\' of the parameter \'fortunes\' did not match the type of the data p" +
+                "assed to the template.");
+    }
+    else
+    {
+        this._fortunesField = ((global::System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>>)(this.Session["fortunes"]));
+        fortunesValueAcquired = true;
+    }
+}
+if ((fortunesValueAcquired == false))
+{
+    object data = global::System.Runtime.Remoting.Messaging.CallContext.LogicalGetData("fortunes");
+    if ((data != null))
+    {
+        if ((typeof(global::System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>>).IsAssignableFrom(data.GetType()) == false))
+        {
+            this.Error("The type \'System.Collections.Generic.List<System.Collections.Generic.KeyValuePair" +
+                    "<int, string>>\' of the parameter \'fortunes\' did not match the type of the data p" +
+                    "assed to the template.");
+        }
+        else
+        {
+            this._fortunesField = ((global::System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>>)(data));
+        }
+    }
+}
+
+
+    }
+}
+
+
+        
+        #line default
+        #line hidden
+    }
+    
+    #line default
+    #line hidden
+    #region Base class
+    /// <summary>
+    /// Base class for this transformation
+    /// </summary>
+    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "10.0.0.0")]
+    public class FortunesBase
+    {
+        #region Fields
+        private global::System.Text.StringBuilder generationEnvironmentField;
+        private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
+        private global::System.Collections.Generic.List<int> indentLengthsField;
+        private string currentIndentField = "";
+        private bool endsWithNewline;
+        private global::System.Collections.Generic.IDictionary<string, object> sessionField;
+        #endregion
+        #region Properties
+        /// <summary>
+        /// The string builder that generation-time code is using to assemble generated output
+        /// </summary>
+        protected System.Text.StringBuilder GenerationEnvironment
+        {
+            get
+            {
+                if ((this.generationEnvironmentField == null))
+                {
+                    this.generationEnvironmentField = new global::System.Text.StringBuilder();
+                }
+                return this.generationEnvironmentField;
+            }
+            set
+            {
+                this.generationEnvironmentField = value;
+            }
+        }
+        /// <summary>
+        /// The error collection for the generation process
+        /// </summary>
+        public System.CodeDom.Compiler.CompilerErrorCollection Errors
+        {
+            get
+            {
+                if ((this.errorsField == null))
+                {
+                    this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
+                }
+                return this.errorsField;
+            }
+        }
+        /// <summary>
+        /// A list of the lengths of each indent that was added with PushIndent
+        /// </summary>
+        private System.Collections.Generic.List<int> indentLengths
+        {
+            get
+            {
+                if ((this.indentLengthsField == null))
+                {
+                    this.indentLengthsField = new global::System.Collections.Generic.List<int>();
+                }
+                return this.indentLengthsField;
+            }
+        }
+        /// <summary>
+        /// Gets the current indent we use when adding lines to the output
+        /// </summary>
+        public string CurrentIndent
+        {
+            get
+            {
+                return this.currentIndentField;
+            }
+        }
+        /// <summary>
+        /// Current transformation session
+        /// </summary>
+        public virtual global::System.Collections.Generic.IDictionary<string, object> Session
+        {
+            get
+            {
+                return this.sessionField;
+            }
+            set
+            {
+                this.sessionField = value;
+            }
+        }
+        #endregion
+        #region Transform-time helpers
+        /// <summary>
+        /// Write text directly into the generated output
+        /// </summary>
+        public void Write(string textToAppend)
+        {
+            if (string.IsNullOrEmpty(textToAppend))
+            {
+                return;
+            }
+            // If we're starting off, or if the previous text ended with a newline,
+            // we have to append the current indent first.
+            if (((this.GenerationEnvironment.Length == 0) 
+                        || this.endsWithNewline))
+            {
+                this.GenerationEnvironment.Append(this.currentIndentField);
+                this.endsWithNewline = false;
+            }
+            // Check if the current text ends with a newline
+            if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
+            {
+                this.endsWithNewline = true;
+            }
+            // This is an optimization. If the current indent is "", then we don't have to do any
+            // of the more complex stuff further down.
+            if ((this.currentIndentField.Length == 0))
+            {
+                this.GenerationEnvironment.Append(textToAppend);
+                return;
+            }
+            // Everywhere there is a newline in the text, add an indent after it
+            textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
+            // If the text ends with a newline, then we should strip off the indent added at the very end
+            // because the appropriate indent will be added when the next time Write() is called
+            if (this.endsWithNewline)
+            {
+                this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
+            }
+            else
+            {
+                this.GenerationEnvironment.Append(textToAppend);
+            }
+        }
+        /// <summary>
+        /// Write text directly into the generated output
+        /// </summary>
+        public void WriteLine(string textToAppend)
+        {
+            this.Write(textToAppend);
+            this.GenerationEnvironment.AppendLine();
+            this.endsWithNewline = true;
+        }
+        /// <summary>
+        /// Write formatted text directly into the generated output
+        /// </summary>
+        public void Write(string format, params object[] args)
+        {
+            this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+        }
+        /// <summary>
+        /// Write formatted text directly into the generated output
+        /// </summary>
+        public void WriteLine(string format, params object[] args)
+        {
+            this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
+        }
+        /// <summary>
+        /// Raise an error
+        /// </summary>
+        public void Error(string message)
+        {
+            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+            error.ErrorText = message;
+            this.Errors.Add(error);
+        }
+        /// <summary>
+        /// Raise a warning
+        /// </summary>
+        public void Warning(string message)
+        {
+            System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
+            error.ErrorText = message;
+            error.IsWarning = true;
+            this.Errors.Add(error);
+        }
+        /// <summary>
+        /// Increase the indent
+        /// </summary>
+        public void PushIndent(string indent)
+        {
+            if ((indent == null))
+            {
+                throw new global::System.ArgumentNullException("indent");
+            }
+            this.currentIndentField = (this.currentIndentField + indent);
+            this.indentLengths.Add(indent.Length);
+        }
+        /// <summary>
+        /// Remove the last indent that was added with PushIndent
+        /// </summary>
+        public string PopIndent()
+        {
+            string returnValue = "";
+            if ((this.indentLengths.Count > 0))
+            {
+                int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
+                this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
+                if ((indentLength > 0))
+                {
+                    returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
+                    this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
+                }
+            }
+            return returnValue;
+        }
+        /// <summary>
+        /// Remove any indentation
+        /// </summary>
+        public void ClearIndent()
+        {
+            this.indentLengths.Clear();
+            this.currentIndentField = "";
+        }
+        #endregion
+        #region ToString Helpers
+        /// <summary>
+        /// Utility class to produce culture-oriented representation of an object as a string.
+        /// </summary>
+        public class ToStringInstanceHelper
+        {
+            private System.IFormatProvider formatProviderField  = global::System.Globalization.CultureInfo.InvariantCulture;
+            /// <summary>
+            /// Gets or sets format provider to be used by ToStringWithCulture method.
+            /// </summary>
+            public System.IFormatProvider FormatProvider
+            {
+                get
+                {
+                    return this.formatProviderField ;
+                }
+                set
+                {
+                    if ((value != null))
+                    {
+                        this.formatProviderField  = value;
+                    }
+                }
+            }
+            /// <summary>
+            /// This is called from the compile/run appdomain to convert objects within an expression block to a string
+            /// </summary>
+            public string ToStringWithCulture(object objectToConvert)
+            {
+                if ((objectToConvert == null))
+                {
+                    throw new global::System.ArgumentNullException("objectToConvert");
+                }
+                System.Type t = objectToConvert.GetType();
+                System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
+                            typeof(System.IFormatProvider)});
+                if ((method == null))
+                {
+                    return objectToConvert.ToString();
+                }
+                else
+                {
+                    return ((string)(method.Invoke(objectToConvert, new object[] {
+                                this.formatProviderField })));
+                }
+            }
+        }
+        private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
+        public ToStringInstanceHelper ToStringHelper
+        {
+            get
+            {
+                return this.toStringHelperField;
+            }
+        }
+        #endregion
+    }
+    #endregion
+}

+ 14 - 0
frameworks/CSharp/revenj/Revenj.Bench/Fortunes.tt

@@ -0,0 +1,14 @@
+<#@ template language="C#" #>
+<#@ assembly name="System.Web" #>
+<#@ parameter type="System.Collections.Generic.List<System.Collections.Generic.KeyValuePair<int, string>>" name="fortunes" #>
+<!DOCTYPE html>
+<html>
+<head><title>Fortunes</title></head>
+<body><table><tr><th>id</th><th>message</th></tr>
+<# for (var i=0; i<fortunes.Count;i++) {
+	var f = fortunes[i]; #>
+<tr><td><# Write(f.Key.ToString()); #></td><td><# Write(System.Web.HttpUtility.HtmlEncode(f.Value)); #></td></tr>
+<# } #>
+</table>
+</body>
+</html>

+ 29 - 9
frameworks/CSharp/revenj/Revenj.Bench/RestService.cs

@@ -1,5 +1,5 @@
 using System;
-using System.ComponentModel;
+using System.Collections.Generic;
 using System.IO;
 using System.ServiceModel;
 using System.ServiceModel.Web;
@@ -17,28 +17,27 @@ namespace Revenj.Bench
 	{
 		[OperationContract]
 		[WebGet(UriTemplate = "/plaintext")]
-		[Description("Plain text response")]
 		Stream PlainText();
 
 		[OperationContract]
 		[WebGet(UriTemplate = "/json")]
-		[Description("JSON response")]
 		Stream JSON();
 
 		[OperationContract]
 		[WebGet(UriTemplate = "/db")]
-		[Description("Single database query")]
 		Stream SingleQuery();
 
 		[OperationContract]
 		[WebGet(UriTemplate = "/queries/{count}")]
-		[Description("Multiple database queries")]
 		Stream MultipleQueries(string count);
 
 		[OperationContract]
 		[WebGet(UriTemplate = "/updates/{count}")]
-		[Description("Database updates")]
 		Stream Updates(string count);
+
+		[OperationContract]
+		[WebGet(UriTemplate = "/fortunes")]
+		Stream Fortunes();
 	}
 
 	public class RestService : IRestService
@@ -95,7 +94,7 @@ namespace Revenj.Bench
 		{
 			var id = Random.Next(10000) + 1;
 			var ctx = GetContext(Services);
-			var world = ctx.Repository.Find(IDs[id]);
+			var world = ctx.WorldRepository.Find(IDs[id]);
 			return ReturnJSON(world, ctx.Stream);
 		}
 
@@ -144,11 +143,32 @@ namespace Revenj.Bench
 			for (int i = 0; i < result.Length; i++)
 				result[i].randomNumber = Random.Next(10000) + 1;
 			Array.Sort(result, ASC);
-			ctx.Repository.Update(result);
+			ctx.WorldRepository.Update(result);
 			var cms = ctx.Stream;
 			result.Serialize(cms);
 			ThreadContext.Response.ContentType = "application/json";
 			return cms;
 		}
+
+		private static readonly Comparison<KeyValuePair<int, string>> Comparison = (l, r) => string.Compare(l.Value, r.Value, StringComparison.Ordinal);
+
+		public Stream Fortunes()
+		{
+			var ctx = GetContext(Services);
+			var fortunes = ctx.FortuneRepository.Search();
+			var list = new List<KeyValuePair<int, string>>(fortunes.Length + 1);
+			foreach (var f in fortunes)
+				list.Add(new KeyValuePair<int, string>(f.id, f.message));
+			list.Add(new KeyValuePair<int, string>(0, "Additional fortune added at request time."));
+			list.Sort(Comparison);
+			var cms = ctx.Stream;
+			var writer = cms.GetWriter();
+			var template = new Fortunes(list, writer);
+			template.TransformText();
+			writer.Flush();
+			cms.Position = 0;
+			ThreadContext.Response.ContentType = "text/html; charset=UTF-8";
+			return cms;
+	}
 	}
-}
+}

+ 14 - 0
frameworks/CSharp/revenj/Revenj.Bench/Revenj.Bench.csproj

@@ -75,9 +75,16 @@
     <Reference Include="System.Core" />
     <Reference Include="System.ServiceModel" />
     <Reference Include="System.ServiceModel.Web" />
+    <Reference Include="System.Web" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Context.cs" />
+    <Compile Include="Fortunes.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Fortunes.tt</DependentUpon>
+    </Compile>
+    <Compile Include="FortuneTemplate.cs" />
     <Compile Include="RestService.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -85,11 +92,18 @@
       <Link>Revenj.Http.exe.config</Link>
       <SubType>Designer</SubType>
     </None>
+    <None Include="Fortunes.tt">
+      <Generator>TextTemplatingFilePreprocessor</Generator>
+      <LastGenOutput>Fortunes.cs</LastGenOutput>
+    </None>
     <None Include="model.dsl" />
   </ItemGroup>
   <ItemGroup>
     <Folder Include="Properties\" />
   </ItemGroup>
+  <ItemGroup>
+    <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.

+ 5 - 1
frameworks/CSharp/revenj/Revenj.Bench/model.dsl

@@ -6,4 +6,8 @@
 		int id;
 		int randomNumber from randomnumber;
 	}
-}
+	sql Fortune from fortune {
+	    int id;
+	    String message;
+	}
+}

+ 2 - 0
frameworks/CSharp/revenj/benchmark_config.json

@@ -8,6 +8,7 @@
       "query_url": "/bench/queries/",
       "plaintext_url": "/bench/plaintext",
       "update_url": "/bench/updates/",
+      "fortune_url": "/bench/fortunes",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",
@@ -30,6 +31,7 @@
       "query_url": "/bench/queries/",
       "plaintext_url": "/bench/plaintext",
       "update_url": "/bench/updates/",
+      "fortune_url": "/bench/fortunes",
       "port": 8080,
       "approach": "Realistic",
       "classification": "Platform",

+ 1 - 1
frameworks/CSharp/revenj/install.sh

@@ -1,3 +1,3 @@
 #!/bin/bash
 
-fw_depends mono java
+fw_depends mono java dsl_platform

+ 6 - 17
frameworks/CSharp/revenj/setup.ps1

@@ -3,6 +3,9 @@ param($action)
 if (!$TROOT) {
   $TROOT = "C:\FrameworkBenchmarks\frameworks\CSharp\revenj"
 }
+if (!$IROOT) {
+  $IROOT = "C:\FrameworkBenchmarks\installs"
+}
 if (!$DBHOST) {
   $DBHOST = "localhost"
 }
@@ -13,7 +16,6 @@ $msbuild = $Env:windir + "\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe"
 $java=$Env:JAVA_HOME + "\bin\java"
 $dslclc=$TROOT + "\dsl-clc.jar"
 $httpZip=$TROOT + "\http-server.zip"
-$dslZip=$TROOT + "\dsl-compiler.zip"
 $sln=$TROOT + "\Revenj.Bench.sln"
 $revenj=$TROOT + "\exe\Revenj.Http.exe"
 $exe=$TROOT + "\exe\"
@@ -34,33 +36,20 @@ if ($action -eq 'start') {
 	if (Test-Path $TROOT/http-server.zip) {
 	  rm $TROOT/http-server.zip
 	}
-	if (Test-Path $TROOT/dsl-compiler.zip) {
-	  rm $TROOT/dsl-compiler.zip
-	}
-	if (Test-Path $TROOT/dsl-compiler.exe) {
-	  rm $TROOT/dsl-compiler.exe
-	}
 
 	echo "Download DSL compiler client"
 	$client = new-object System.Net.WebClient
-	$client.DownloadFile( "https://github.com/ngs-doo/dsl-compiler-client/releases/download/1.5.0/dsl-clc.jar", $dslclc )
+	$client.DownloadFile( "https://github.com/ngs-doo/dsl-compiler-client/releases/download/1.7.0/dsl-clc.jar", $dslclc )
 
 	echo "Download Revenj HTTP server"
 	$client = new-object System.Net.WebClient
-	$client.DownloadFile( "https://github.com/ngs-doo/revenj/releases/download/1.2.1/http-server.zip", $httpZip )
+	$client.DownloadFile( "https://github.com/ngs-doo/revenj/releases/download/1.3.1/http-server.zip", $httpZip )
 
 	echo "Unzipping HTTP server"
 	[System.IO.Compression.ZipFile]::ExtractToDirectory($httpZip, $exe)
 
-	echo "Download DSL compiler for Revenj.NET 1.2.1"
-	$client = new-object System.Net.WebClient
-	$client.DownloadFile( "https://github.com/ngs-doo/revenj/releases/download/1.2.1/dsl-compiler.zip", $dslZip )
-
-	echo "Unzipping DSL compiler"
-	[System.IO.Compression.ZipFile]::ExtractToDirectory($dslZip, $TROOT)
-	
 	echo "Compiling the server model and downloading DSL Platform compiler..."
-	&$java -jar $dslclc temp=$TROOT/tmp/ force dsl=$TROOT/Revenj.Bench manual-json revenj.net=$TROOT/exe/ServerModel.dll no-prompt dependencies:revenj.net=$TROOT/exe download compiler=$TROOT/dsl-compiler.exe
+	&$java -jar $dslclc temp=$TROOT/tmp/ force dsl=$TROOT/Revenj.Bench manual-json revenj.net=$TROOT/exe/ServerModel.dll no-prompt dependencies:revenj.net=$TROOT/exe compiler=$IROOT/dsl-compiler.exe
 
 	echo "Compiling the benchmark project..."
 	&$msbuild $sln /p:Configuration=Release /t:Rebuild

+ 7 - 14
frameworks/CSharp/revenj/setup.sh

@@ -1,36 +1,29 @@
 #!/bin/bash
 
-fw_depends java mono
+fw_depends java mono dsl_platform
 
 echo "Cleaning up..."
-rm -rf $TROOT/exe $TROOT/tmp $TROOT/dsl-clc.jar $TROOT/http-server.zip  $TROOT/dsl-compiler.zip $TROOT/dsl-compiler.exe
+rm -rf $TROOT/exe $TROOT/tmp $TROOT/dsl-clc.jar $TROOT/http-server.zip
 
 echo "Download DSL compiler client"
-wget -O $TROOT/dsl-clc.jar https://github.com/ngs-doo/dsl-compiler-client/releases/download/1.5.0/dsl-clc.jar
+wget -O $TROOT/dsl-clc.jar https://github.com/ngs-doo/dsl-compiler-client/releases/download/1.7.0/dsl-clc.jar
 
-echo "Download Revenj.NET HTTP server 1.2.1"
-wget -O $TROOT/http-server.zip https://github.com/ngs-doo/revenj/releases/download/1.2.1/http-server.zip
+echo "Download Revenj.NET HTTP server 1.3.1"
+wget -O $TROOT/http-server.zip https://github.com/ngs-doo/revenj/releases/download/1.3.1/http-server.zip
 
 echo "Unzipping HTTP server"
 unzip $TROOT/http-server.zip -d $TROOT/exe
 
-echo "Download DSL compiler for Revenj.NET 1.2.1"
-wget -O $TROOT/dsl-compiler.zip https://github.com/ngs-doo/revenj/releases/download/1.2.1/dsl-compiler.zip
-
-echo "Unzipping DSL compiler"
-unzip $TROOT/dsl-compiler.zip -d $TROOT
-
 echo "Compiling the server model and downloading dependencies..."
 java -jar $TROOT/dsl-clc.jar \
 	temp=$TROOT/tmp/ \
 	force \
 	dsl=$TROOT/Revenj.Bench \
 	manual-json \
-	compiler=$TROOT/dsl-compiler.exe \
+	compiler=$IROOT/dsl-compiler.exe \
 	revenj.net=$TROOT/exe/ServerModel.dll \
 	no-prompt \
-	dependencies:revenj.net=$TROOT/exe \
-	download
+	dependencies:revenj.net=$TROOT/exe
 
 echo "Compiling the benchmark project..."
 xbuild $TROOT/Revenj.Bench/Revenj.Bench.csproj /t:Rebuild /p:Configuration=Release

+ 3 - 1
frameworks/CSharp/revenj/source_code

@@ -1,4 +1,6 @@
 ./revenj/Revenj.Bench/Context.cs
-./revenj/Revenj.Bench/RestService.cs
+./revenj/Revenj.Bench/Fortunes.tt
+./revenj/Revenj.Bench/FortuneTemplate.cs
 ./revenj/Revenj.Bench/model.dsl
+./revenj/Revenj.Bench/RestService.cs
 ./revenj/Revenj.Http.exe.config

+ 0 - 5
frameworks/Crystal/moonshine/.gitignore

@@ -1,5 +0,0 @@
-.deps
-.deps.lock
-libs/
-.crystal
-.shards

+ 0 - 5
frameworks/Crystal/moonshine/README.md

@@ -1,5 +0,0 @@
-# Crystal-Moonshine
-
-This is the [Moonshine](https://github.com/dhruvrajvanshi/Moonshine) test of the Framework Benchmarks. Crystal is a new language that closely resembles Ruby with a goal of removing typed variables and parameters (instead inferencing), whilst maintaining top speed through bindings into C.
-
-Moonshine is a minimal web framework for the Crystal language.

+ 0 - 28
frameworks/Crystal/moonshine/benchmark_config.json

@@ -1,28 +0,0 @@
-{
-  "framework": "moonshine",
-  "tests": [{
-    "default": {
-      "setup_file": "setup-postgres",
-      "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": "Fullstack",
-      "database": "Postgres",
-      "framework": "moonshine",
-      "language": "Crystal",
-      "orm": "micro",
-      "platform": "Crystal",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "Moonshine",
-      "notes": "",
-      "versus": "ruby"
-    }
-  }]
-}

+ 0 - 157
frameworks/Crystal/moonshine/server-postgres.cr

@@ -1,157 +0,0 @@
-require "moonshine"
-require "pg"
-require "html/builder"
-
-include Moonshine
-include Moonshine::Utils::Shortcuts
-
-# Compose Objects (like Hash) to have a to_json method
-require "json/to_json"
-
-DB = PG.connect("postgres://benchmarkdbuser:benchmarkdbpass@#{ENV["DBHOST"]? || "127.0.0.1"}/hello_world")
-app = App.new
-
-class CONTENT
-  UTF8 = "; charset=UTF-8"
-  JSON = "application/json" + UTF8
-  PLAIN = "text/plain"
-  HTML = "text/html" + UTF8
-end
-
-ID_MAXIMUM = 10_000
-
-app.response_middleware do |req, res|
-    res.headers["Server"] = "Moonshine"
-    res.headers["Date"] = Time.now.to_s
-    res
-end
-
-private def randomWorld
-  id = rand(1..ID_MAXIMUM)
-  result = DB.exec({Int32, Int32}, "SELECT id, randomNumber FROM world WHERE id = $1", [id]).rows.first
-  {:id => result[0], :randomNumber => result[1]}
-end
-
-private def setWorld(world)
-  DB.exec("UPDATE world set randomNumber = $1 where id = $2", [world[:randomNumber], world[:id]])
-  world
-end
-
-private def fortunes
-  data = [] of  Hash(Symbol, (String | Int32))
-
-  DB.exec({Int32, String}, "select id, message from Fortune").rows.each do |row|
-    data.push({:id => row[0], :message => row[1]})
-  end
-  data
-end
-
-private def sanitizedQueryCount(request)
-  begin
-    queries = request.get["queries"].to_i
-  rescue
-    queries = 1
-  end
-  queries = 1 if queries < 1
-  queries = 500 if queries > 500
-  queries
-end
-
-#
-# Basic Tests
-#
-
-# Test 1: JSON Serialization
-app.get "/json", do |request|
-  res = ok({ :message => "Hello, World!" }.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-# Test 6: Plaintext
-app.get "/plaintext", do |request|
-  res = ok("Hello, World!")
-  res.headers["Content-type"] = CONTENT::PLAIN
-  res
-end
-
-#
-# Postgres DatabaseTests
-#
-
-# Postgres Test 2: Single database query
-app.get "/db", do |request|
-  res = ok(randomWorld.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-# Postgres Test 3: Multiple database query
-app.get "/queries", do |request|
-  results = (1..sanitizedQueryCount(request)).map do
-    randomWorld
-  end
-
-  res = ok(results.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-# Postgres Test 4: Fortunes
-app.get "/fortunes", do |request|
-  data = fortunes
-  
-  additional_fortune = {
-    :id => 0,
-    :message => "Additional fortune added at request time."
-  }
-  data.push(additional_fortune)
-
-  data.sort! do |a, b|
-    a[:message].to_s <=> b[:message].to_s
-  end
-
-  # New builder for each request!
-  html = HTML::Builder.new.build do
-    html {
-      head {
-        title { text "Fortunes" }
-      }
-      body {
-        table {
-          tr {
-            thead { text "id" }
-            thead { text "message" }
-          }
-          data.each { |e|
-            tr {
-              td { text e[:id].to_s }
-              td { text e[:message].to_s }
-            }
-          }
-        }
-      }
-    }
-  end
-
-  # Doctype not available in builder
-  # builder only supports `thead`, tests need to see `th`
-  res = ok("<!doctype html>" + html.gsub("thead", "th"))
-  res.headers["Content-type"] = CONTENT::HTML
-  res
-end
-
-# Postgres Test 5: Database Updates
-app.get "/updates", do |request|
-  updated = (1..sanitizedQueryCount(request)).map do
-    world = randomWorld
-    world[:randomNumber] = rand(1..ID_MAXIMUM)
-    setWorld(world)
-  end
-
-  res = ok(updated.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-app.run(8080)

+ 0 - 158
frameworks/Crystal/moonshine/server-redis.cr

@@ -1,158 +0,0 @@
-require "moonshine"
-require "redis"
-require "html/builder"
-
-include Moonshine
-include Moonshine::Utils::Shortcuts
-
-# Compose Objects (like Hash) to have a to_json method
-require "json/to_json"
-
-REDIS = Redis.new
-app = App.new
-
-class CONTENT
-  UTF8 = "; charset=UTF-8"
-  JSON = "application/json" #+ UTF8
-  PLAIN = "text/plain"
-  HTML = "text/html" #+ UTF8
-end
-
-ID_MAXIMUM = 10_000
-
-app.response_middleware do |req, res|
-    res.headers["Server"] = "Moonshine"
-    res.headers["Date"] = Time.now.to_s
-    res
-end
-
-private def randomWorld
-  id = rand(1..ID_MAXIMUM)
-  num = REDIS.get("world:" + id.to_s)
-  { :id => id, :randomNumber => num }
-end
-
-private def setWorld(world)
-  id = "world:" + world[:id].to_s
-  REDIS.set(id, world[:randomNumber])
-  world
-end
-
-private def fortunes
-  data = [] of  Hash(Symbol, (String | Int32))
-
-  REDIS.lrange("fortunes", 0, -1).each_with_index do |e, i|
-    data.push({:id => i + 1, :message => e.to_s})
-  end
-  data
-end
-
-private def sanitizedQueryCount(request)
-  begin
-    queries = request.get["queries"].to_i
-  rescue
-    queries = 1
-  end
-  queries = 1 if queries < 1
-  queries = 500 if queries > 500
-  queries
-end
-
-#
-# Basic Tests
-#
-
-# Test 1: JSON Serialization
-app.get "/json", do |request|
-  res = ok({ :message => "Hello, World!" }.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-# Test 6: Plaintext
-app.get "/plaintext", do |request|
-  res = ok("Hello, World!")
-  res.headers["Content-type"] = CONTENT::PLAIN
-  res
-end
-
-#
-# Redis DatabaseTests
-#
-
-# Redis Test 2: Single database query
-app.get "/db", do |request|
-  res = ok(randomWorld.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-# Redis Test 3: Multiple database query
-app.get "/queries", do |request|
-  results = (1..sanitizedQueryCount(request)).map do
-    randomWorld
-  end
-
-  res = ok(results.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-# Redis Test 4: Fortunes
-app.get "/fortunes", do |request|
-  data = fortunes
-  
-  additional_fortune = {
-    :id => 0,
-    :message => "Additional fortune added at request time."
-  }
-  data.push(additional_fortune)
-
-  data.sort! do |a, b|
-    a[:message].to_s <=> b[:message].to_s
-  end
-
-  # New builder for each request!
-  html = HTML::Builder.new.build do
-    html {
-      head {
-        title { text "Fortunes" }
-      }
-      body {
-        table {
-          tr {
-            thead { text "id" }
-            thead { text "message" }
-          }
-          data.each { |e|
-            tr {
-              td { text e[:id].to_s }
-              td { text e[:message].to_s }
-            }
-          }
-        }
-      }
-    }
-  end
-
-  # Doctype not available in builder
-  # builder only supports `thead`, tests need to see `th`
-  res = ok("<!doctype html>" + html.gsub("thead", "th"))
-  res.headers["Content-type"] = CONTENT::HTML
-  res
-end
-
-# Redis Test 5: Database Updates
-app.get "/updates", do |request|
-  updated = (1..sanitizedQueryCount(request)).map do
-    world = randomWorld
-    world[:randomNumber] = rand(1..ID_MAXIMUM)
-    setWorld(world)
-  end
-
-  res = ok(updated.to_json)
-  res.headers["Content-type"] = CONTENT::JSON
-  res
-end
-
-app.run(8080)

+ 0 - 7
frameworks/Crystal/moonshine/setup-postgres.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends crystal
-
-crystal deps install
-
-crystal server-postgres.cr &

+ 0 - 7
frameworks/Crystal/moonshine/setup-redis.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends crystal
-
-crystal deps install
-
-crystal server-redis.cr &

+ 0 - 15
frameworks/Crystal/moonshine/shard.yml

@@ -1,15 +0,0 @@
-name: "moonshine"
-version: "0.0.1"
-
-dependencies:
-  pg:
-    github: "will/crystal-pg"
-    version: ">= 0.4.3"
-  moonshine:
-    github: "dhruvrajvanshi/Moonshine"
-    branch: master
-  redis:
-    github: "stefanwille/crystal-redis"
-    version: "~> 1.2.1"
-
-license: MIT

+ 0 - 2
frameworks/Go/fasthttp-mysql/.gitignore

@@ -1,2 +0,0 @@
-/pkg/
-/src/github.com/

+ 0 - 51
frameworks/Go/fasthttp-mysql/benchmark_config.json

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

+ 0 - 3
frameworks/Go/fasthttp-mysql/setup.bat

@@ -1,3 +0,0 @@
-set GOPATH=C:\FrameworkBenchmarks\Go\fasthttp-mysql
-go build -o server
-.\server

+ 0 - 14
frameworks/Go/fasthttp-mysql/setup.sh

@@ -1,14 +0,0 @@
-#!/bin/bash
-
-sed -i 's|tcp(.*:3306)|tcp('"${DBHOST}"':3306)|g' server.go
-
-fw_depends go
-
-go get -u github.com/go-sql-driver/mysql
-go get -u github.com/valyala/fasthttp
-go get -u github.com/valyala/quicktemplate/qtc
-
-rm -f ./server
-go generate
-go build -o server
-./server &

+ 0 - 14
frameworks/Go/fasthttp-mysql/setup_prefork.sh

@@ -1,14 +0,0 @@
-#!/bin/bash
-
-sed -i 's|tcp(.*:3306)|tcp('"${DBHOST}"':3306)|g' server.go
-
-fw_depends go
-
-go get -u github.com/go-sql-driver/mysql
-go get -u github.com/valyala/fasthttp
-go get -u github.com/valyala/quicktemplate/qtc
-
-rm -f ./server
-go generate
-go build -o server
-./server -prefork &

+ 0 - 4
frameworks/Go/fasthttp-mysql/source_code

@@ -1,4 +0,0 @@
-./fasthttp-mysql/server.go
-./fasthttp-mysql/src/
-./fasthttp-mysql/src/templates/
-./fasthttp-mysql/src/templates/fortune.qtpl

+ 0 - 22
frameworks/Go/fasthttp-mysql/src/templates/fortune.qtpl

@@ -1,22 +0,0 @@
-{% code
-type Fortune struct {
-	ID int
-	Message string
-}
-%}
-
-{% func FortunePage(rows []Fortune) %}<!DOCTYPE html>
-<html>
-<head>
-<title>Fortunes</title>
-</head>
-<body>
-<table>
-<tr><th>id</th><th>message</th></tr>
-{% for _, r := range rows %}
-<tr><td>{%d r.ID %}</td><td>{%s r.Message %}</td></tr>
-{% endfor %}
-</table>
-</body>
-</html>
-{% endfunc %}

+ 0 - 2
frameworks/Go/fasthttp-postgresql/.gitignore

@@ -1,2 +0,0 @@
-/pkg/
-/src/github.com/

+ 0 - 16
frameworks/Go/fasthttp-postgresql/README.md

@@ -1,16 +0,0 @@
-# [fasthttp](https://github.com/valyala/fasthttp) (GoLang) Benchmarking Test for postgresql
-
-This is the go portion of a [benchmarking test suite](https://www.techempower.com/benchmarks/) comparing a variety of web development platforms.
-
-"Fasthttp is a fast http package for Go."
-
-# This variant uses Postgres via Jack Christensen's pgx library
-
-## Test URLs
-
-    http://localhost:8080/json
-    http://localhost:8080/db
-    http://localhost:8080/queries?queries=[1-500]
-    http://localhost:8080/fortunes
-    http://localhost:8080/updates?queries=[1-500]
-    http://localhost:8080/plaintext

+ 0 - 51
frameworks/Go/fasthttp-postgresql/benchmark_config.json

@@ -1,51 +0,0 @@
-{
-  "framework": "fasthttp-postgresql",
-  "tests": [{
-    "default": {
-      "setup_file": "setup",
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Platform",
-      "database": "Postgres",
-      "framework": "fasthttp",
-      "language": "Go",
-      "orm": "Raw",
-      "platform": "Go",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "fasthttp-postgresql",
-      "notes": "",
-      "versus": "go"
-    },
-    "prefork": {
-      "setup_file": "setup_prefork",
-      "json_url": "/json",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "plaintext_url": "/plaintext",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Platform",
-      "database": "Postgres",
-      "framework": "fasthttp",
-      "language": "Go",
-      "orm": "Raw",
-      "platform": "Go",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "fasthttp-postgresql-prefork",
-      "notes": "",
-      "versus": "go"
-    }
-  }]
-}

+ 0 - 3
frameworks/Go/fasthttp-postgresql/setup.bat

@@ -1,3 +0,0 @@
-set GOPATH=C:\FrameworkBenchmarks\Go\fasthttp-postgresql
-go build -o server
-.\server

+ 0 - 14
frameworks/Go/fasthttp-postgresql/setup.sh

@@ -1,14 +0,0 @@
-#!/bin/bash
-
-sed -i 's|localhost|'"${DBHOST}"'|g' server.go
-
-fw_depends go
-
-go get -u github.com/jackc/pgx
-go get -u github.com/valyala/fasthttp
-go get -u github.com/valyala/quicktemplate/qtc
-
-rm -f ./server
-go generate
-go build -o server
-./server &

+ 0 - 14
frameworks/Go/fasthttp-postgresql/setup_prefork.sh

@@ -1,14 +0,0 @@
-#!/bin/bash
-
-sed -i 's|localhost|'"${DBHOST}"'|g' server.go
-
-fw_depends go
-
-go get -u github.com/jackc/pgx
-go get -u github.com/valyala/fasthttp
-go get -u github.com/valyala/quicktemplate/qtc
-
-rm -f ./server
-go generate
-go build -o server
-./server -prefork &

+ 0 - 4
frameworks/Go/fasthttp-postgresql/source_code

@@ -1,4 +0,0 @@
-./fasthttp-postgresql/server.go
-./fasthttp-postgresql/src/
-./fasthttp-postgresql/src/templates/
-./fasthttp-postgresql/src/templates/fortune.qtpl

+ 1 - 1
frameworks/Go/fasthttp-mysql/README.md → frameworks/Go/fasthttp/README.md

@@ -1,4 +1,4 @@
-# [fasthttp](https://github.com/valyala/fasthttp) (GoLang) Benchmarking Test for mysql
+# [fasthttp](https://github.com/valyala/fasthttp) (GoLang) Benchmarking Test
 
 This is the go portion of a [benchmarking test suite](https://www.techempower.com/benchmarks/) comparing a variety of web development platforms.
 

+ 97 - 0
frameworks/Go/fasthttp/benchmark_config.json

@@ -0,0 +1,97 @@
+{
+  "framework": "fasthttp",
+  "tests": [{
+    "mysql": {
+      "setup_file": "setup-mysql",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MySQL",
+      "framework": "fasthttp",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "fasthttp-mysql",
+      "notes": "",
+      "versus": "go"
+    },
+    "mysql-prefork": {
+      "setup_file": "setup-mysql-prefork",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MySQL",
+      "framework": "fasthttp",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "fasthttp-mysql-prefork",
+      "notes": "",
+      "versus": "go"
+    },
+    "postgresql": {
+      "setup_file": "setup-postgresql",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Postgres",
+      "framework": "fasthttp",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "fasthttp-postgresql",
+      "notes": "",
+      "versus": "go"
+    },
+    "postgresql-prefork": {
+      "setup_file": "setup-postgresql-prefork",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Postgres",
+      "framework": "fasthttp",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "fasthttp-postgresql-prefork",
+      "notes": "",
+      "versus": "go"
+    }
+  }]
+}

+ 14 - 0
frameworks/Go/fasthttp/setup-mysql-prefork.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+sed -i 's|tcp(.*:3306)|tcp('"${DBHOST}"':3306)|g' src/server-mysql/server.go
+
+fw_depends go
+
+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/quicktemplate/qtc
+
+rm -f ./server-mysql
+GOPATH=`pwd` go generate templates
+GOPATH=`pwd` go build server-mysql
+./server-mysql -prefork &

+ 14 - 0
frameworks/Go/fasthttp/setup-mysql.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+sed -i 's|tcp(.*:3306)|tcp('"${DBHOST}"':3306)|g' src/server-mysql/server.go
+
+fw_depends go
+
+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/quicktemplate/qtc
+
+rm -f ./server-mysql
+GOPATH=`pwd` go generate templates
+GOPATH=`pwd` go build server-mysql
+./server-mysql &

+ 14 - 0
frameworks/Go/fasthttp/setup-postgresql-prefork.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+sed -i 's|localhost|'"${DBHOST}"'|g' src/server-postgresql/server.go
+
+fw_depends go
+
+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/quicktemplate/qtc
+
+rm -f ./server-postgresql
+GOPATH=`pwd` go generate templates
+GOPATH=`pwd` go build server-postgresql
+./server-postgresql -prefork &

+ 14 - 0
frameworks/Go/fasthttp/setup-postgresql.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+sed -i 's|localhost|'"${DBHOST}"'|g' src/server-postgresql/server.go
+
+fw_depends go
+
+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/quicktemplate/qtc
+
+rm -f ./server-postgresql
+GOPATH=`pwd` go generate templates
+GOPATH=`pwd` go build server-postgresql
+./server-postgresql &

+ 3 - 0
frameworks/Go/fasthttp/setup.bat

@@ -0,0 +1,3 @@
+set GOPATH=C:\FrameworkBenchmarks\Go\fasthttp
+go build server-mysql
+.\server-mysql

+ 8 - 0
frameworks/Go/fasthttp/source_code

@@ -0,0 +1,8 @@
+./fasthttp/server.go
+./fasthttp/src/
+./fasthttp/src/common/common.go
+./fasthttp/src/server-mysql/server.go
+./fasthttp/src/server-postgresql/server.go
+./fasthttp/src/templates/
+./fasthttp/src/templates/aux.go
+./fasthttp/src/templates/fortune.qtpl

+ 123 - 0
frameworks/Go/fasthttp/src/common/common.go

@@ -0,0 +1,123 @@
+package common
+
+import (
+	"encoding/json"
+	"flag"
+	"log"
+	"math/rand"
+	"net"
+	"os"
+	"os/exec"
+	"runtime"
+	"sync"
+
+	"github.com/valyala/fasthttp"
+	"github.com/valyala/fasthttp/reuseport"
+
+	"templates"
+)
+
+const worldRowCount = 10000
+
+type JSONResponse struct {
+	Message string `json:"message"`
+}
+
+type World struct {
+	Id           int32 `json:"id"`
+	RandomNumber int32 `json:"randomNumber"`
+}
+
+var (
+	listenAddr = flag.String("listenAddr", ":8080", "Address to listen to")
+	Prefork    = flag.Bool("prefork", false, "use prefork")
+	child      = flag.Bool("child", false, "is child proc")
+)
+
+func JSONHandler(ctx *fasthttp.RequestCtx) {
+	r := jsonResponsePool.Get().(*JSONResponse)
+	r.Message = "Hello, World!"
+	JSONMarshal(ctx, r)
+	jsonResponsePool.Put(r)
+}
+
+var jsonResponsePool = &sync.Pool{
+	New: func() interface{} {
+		return &JSONResponse{}
+	},
+}
+
+func PlaintextHandler(ctx *fasthttp.RequestCtx) {
+	ctx.SetContentType("text/plain")
+	ctx.WriteString("Hello, World!")
+}
+
+func JSONMarshal(ctx *fasthttp.RequestCtx, v interface{}) {
+	ctx.SetContentType("application/json")
+	if err := json.NewEncoder(ctx).Encode(v); err != nil {
+		log.Fatalf("error in json.Encoder.Encode: %s", err)
+	}
+}
+
+func RandomWorldNum() int {
+	return rand.Intn(worldRowCount) + 1
+}
+
+func GetQueriesCount(ctx *fasthttp.RequestCtx) int {
+	n := ctx.QueryArgs().GetUintOrZero("queries")
+	if n < 1 {
+		n = 1
+	} else if n > 500 {
+		n = 500
+	}
+	return n
+}
+
+type FortunesByMessage []templates.Fortune
+
+func (s FortunesByMessage) Len() int           { return len(s) }
+func (s FortunesByMessage) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
+func (s FortunesByMessage) Less(i, j int) bool { return s[i].Message < s[j].Message }
+
+type WorldsByID []World
+
+func (w WorldsByID) Len() int           { return len(w) }
+func (w WorldsByID) Swap(i, j int)      { w[i], w[j] = w[j], w[i] }
+func (w WorldsByID) Less(i, j int) bool { return w[i].Id < w[j].Id }
+
+func GetListener() net.Listener {
+	if !*Prefork {
+		runtime.GOMAXPROCS(runtime.NumCPU())
+		ln, err := net.Listen("tcp4", *listenAddr)
+		if err != nil {
+			log.Fatal(err)
+		}
+		return ln
+	}
+
+	if !*child {
+		children := make([]*exec.Cmd, runtime.NumCPU())
+		for i := range children {
+			children[i] = exec.Command(os.Args[0], "-prefork", "-child")
+			children[i].Stdout = os.Stdout
+			children[i].Stderr = os.Stderr
+			if err := children[i].Start(); err != nil {
+				log.Fatal(err)
+			}
+		}
+		for _, ch := range children {
+			if err := ch.Wait(); err != nil {
+				log.Print(err)
+			}
+		}
+		os.Exit(0)
+		panic("unreachable")
+	}
+
+	runtime.GOMAXPROCS(1)
+	ln, err := reuseport.Listen("tcp4", *listenAddr)
+	if err != nil {
+		log.Fatal(err)
+	}
+	return ln
+}

+ 18 - 137
frameworks/Go/fasthttp-mysql/server.go → frameworks/Go/fasthttp/src/server-mysql/server.go

@@ -1,38 +1,21 @@
-//go:generate qtc -dir=src/templates
 package main
 
 import (
 	"database/sql"
-	"encoding/json"
 	"flag"
 	"log"
-	"math/rand"
-	"net"
-	"os"
-	"os/exec"
 	"runtime"
 	"sort"
-	"sync"
 
 	_ "github.com/go-sql-driver/mysql"
 	"github.com/valyala/fasthttp"
-	"github.com/valyala/fasthttp/reuseport"
 
+	"common"
 	"templates"
 )
 
-type JSONResponse struct {
-	Message string `json:"message"`
-}
-
-type World struct {
-	Id           uint16 `json:"id"`
-	RandomNumber uint16 `json:"randomNumber"`
-}
-
 const (
 	connectionString   = "benchmarkdbuser:benchmarkdbpass@tcp(localhost:3306)/hello_world"
-	worldRowCount      = 10000
 	maxConnectionCount = 40
 )
 
@@ -44,12 +27,6 @@ var (
 	db *sql.DB
 )
 
-var (
-	listenAddr = flag.String("listenAddr", ":8080", "Address to listen to")
-	prefork    = flag.Bool("prefork", false, "use prefork")
-	child      = flag.Bool("child", false, "is child proc")
-)
-
 func main() {
 	flag.Parse()
 
@@ -62,7 +39,7 @@ func main() {
 	}
 
 	dbConnCount := maxConnectionCount
-	if *prefork {
+	if *common.Prefork {
 		dbConnCount = (dbConnCount + runtime.NumCPU() - 1) / runtime.NumCPU()
 	}
 	db.SetMaxIdleConns(dbConnCount)
@@ -76,7 +53,7 @@ func main() {
 		Handler: mainHandler,
 		Name:    "go",
 	}
-	ln := getListener()
+	ln := common.GetListener()
 	if err = s.Serve(ln); err != nil {
 		log.Fatalf("Error when serving incoming connections: %s", err)
 	}
@@ -86,9 +63,9 @@ func mainHandler(ctx *fasthttp.RequestCtx) {
 	path := ctx.Path()
 	switch string(path) {
 	case "/plaintext":
-		plaintextHandler(ctx)
+		common.PlaintextHandler(ctx)
 	case "/json":
-		jsonHandler(ctx)
+		common.JSONHandler(ctx)
 	case "/db":
 		dbHandler(ctx)
 	case "/queries":
@@ -102,40 +79,21 @@ func mainHandler(ctx *fasthttp.RequestCtx) {
 	}
 }
 
-// Test 1: JSON serialization
-func jsonHandler(ctx *fasthttp.RequestCtx) {
-	r := jsonResponsePool.Get().(*JSONResponse)
-	r.Message = "Hello, World!"
-	jsonMarshal(ctx, r)
-	jsonResponsePool.Put(r)
-}
-
-var jsonResponsePool = &sync.Pool{
-	New: func() interface{} {
-		return &JSONResponse{}
-	},
-}
-
-// Test 2: Single database query
 func dbHandler(ctx *fasthttp.RequestCtx) {
-	var w World
+	var w common.World
 	fetchRandomWorld(&w)
-	jsonMarshal(ctx, &w)
+	common.JSONMarshal(ctx, &w)
 }
 
-// Test 3: Multiple database queries
 func queriesHandler(ctx *fasthttp.RequestCtx) {
-	n := getQueriesCount(ctx)
-
-	worlds := make([]World, n)
+	n := common.GetQueriesCount(ctx)
+	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
 		fetchRandomWorld(&worlds[i])
 	}
-
-	jsonMarshal(ctx, worlds)
+	common.JSONMarshal(ctx, worlds)
 }
 
-// Test 4: Fortunes
 func fortuneHandler(ctx *fasthttp.RequestCtx) {
 	rows, err := fortuneSelectStmt.Query()
 	if err != nil {
@@ -153,25 +111,24 @@ func fortuneHandler(ctx *fasthttp.RequestCtx) {
 	rows.Close()
 	fortunes = append(fortunes, templates.Fortune{Message: "Additional fortune added at request time."})
 
-	sort.Sort(FortunesByMessage(fortunes))
+	sort.Sort(common.FortunesByMessage(fortunes))
 
 	ctx.SetContentType("text/html; charset=utf-8")
 	templates.WriteFortunePage(ctx, fortunes)
 }
 
-// Test 5: Database updates
 func updateHandler(ctx *fasthttp.RequestCtx) {
-	n := getQueriesCount(ctx)
+	n := common.GetQueriesCount(ctx)
 
-	worlds := make([]World, n)
+	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
 		w := &worlds[i]
 		fetchRandomWorld(w)
-		w.RandomNumber = uint16(randomWorldNum())
+		w.RandomNumber = int32(common.RandomWorldNum())
 	}
 
 	// sorting is required for insert deadlock prevention.
-	sort.Sort(WorldsByID(worlds))
+	sort.Sort(common.WorldsByID(worlds))
 	txn, err := db.Begin()
 	if err != nil {
 		log.Fatalf("Error starting transaction: %s", err)
@@ -187,55 +144,16 @@ func updateHandler(ctx *fasthttp.RequestCtx) {
 		log.Fatalf("Error when commiting world rows: %s", err)
 	}
 
-	jsonMarshal(ctx, worlds)
-}
-
-// Test 6: Plaintext
-func plaintextHandler(ctx *fasthttp.RequestCtx) {
-	ctx.SetContentType("text/plain")
-	ctx.WriteString("Hello, World!")
+	common.JSONMarshal(ctx, worlds)
 }
 
-func jsonMarshal(ctx *fasthttp.RequestCtx, v interface{}) {
-	ctx.SetContentType("application/json")
-	if err := json.NewEncoder(ctx).Encode(v); err != nil {
-		log.Fatalf("error in json.Encoder.Encode: %s", err)
-	}
-}
-
-func fetchRandomWorld(w *World) {
-	n := randomWorldNum()
+func fetchRandomWorld(w *common.World) {
+	n := common.RandomWorldNum()
 	if err := worldSelectStmt.QueryRow(n).Scan(&w.Id, &w.RandomNumber); err != nil {
 		log.Fatalf("Error scanning world row: %s", err)
 	}
 }
 
-func randomWorldNum() int {
-	return rand.Intn(worldRowCount) + 1
-}
-
-func getQueriesCount(ctx *fasthttp.RequestCtx) int {
-	n := ctx.QueryArgs().GetUintOrZero("queries")
-	if n < 1 {
-		n = 1
-	} else if n > 500 {
-		n = 500
-	}
-	return n
-}
-
-type FortunesByMessage []templates.Fortune
-
-func (s FortunesByMessage) Len() int           { return len(s) }
-func (s FortunesByMessage) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-func (s FortunesByMessage) Less(i, j int) bool { return s[i].Message < s[j].Message }
-
-type WorldsByID []World
-
-func (w WorldsByID) Len() int           { return len(w) }
-func (w WorldsByID) Swap(i, j int)      { w[i], w[j] = w[j], w[i] }
-func (w WorldsByID) Less(i, j int) bool { return w[i].Id < w[j].Id }
-
 func mustPrepare(db *sql.DB, query string) *sql.Stmt {
 	stmt, err := db.Prepare(query)
 	if err != nil {
@@ -243,40 +161,3 @@ func mustPrepare(db *sql.DB, query string) *sql.Stmt {
 	}
 	return stmt
 }
-
-func getListener() net.Listener {
-	if !*prefork {
-		runtime.GOMAXPROCS(runtime.NumCPU())
-		ln, err := net.Listen("tcp4", *listenAddr)
-		if err != nil {
-			log.Fatal(err)
-		}
-		return ln
-	}
-
-	if !*child {
-		children := make([]*exec.Cmd, runtime.NumCPU())
-		for i := range children {
-			children[i] = exec.Command(os.Args[0], "-prefork", "-child")
-			children[i].Stdout = os.Stdout
-			children[i].Stderr = os.Stderr
-			if err := children[i].Start(); err != nil {
-				log.Fatal(err)
-			}
-		}
-		for _, ch := range children {
-			if err := ch.Wait(); err != nil {
-				log.Print(err)
-			}
-		}
-		os.Exit(0)
-		panic("unreachable")
-	}
-
-	runtime.GOMAXPROCS(1)
-	ln, err := reuseport.Listen("tcp4", *listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	return ln
-}

+ 21 - 145
frameworks/Go/fasthttp-postgresql/server.go → frameworks/Go/fasthttp/src/server-postgresql/server.go

@@ -1,39 +1,20 @@
-//go:generate qtc -dir=src/templates
 package main
 
 import (
-	"encoding/json"
 	"flag"
 	"fmt"
 	"log"
-	"math/rand"
-	"net"
-	"os"
-	"os/exec"
 	"runtime"
 	"sort"
-	"sync"
 
 	"github.com/jackc/pgx"
 	"github.com/valyala/fasthttp"
-	"github.com/valyala/fasthttp/reuseport"
 
+	"common"
 	"templates"
 )
 
-type JSONResponse struct {
-	Message string `json:"message"`
-}
-
-type World struct {
-	Id           int32 `json:"id"`
-	RandomNumber int32 `json:"randomNumber"`
-}
-
-const (
-	worldRowCount      = 10000
-	maxConnectionCount = 40
-)
+const maxConnectionCount = 40
 
 var (
 	worldSelectStmt   *pgx.PreparedStatement
@@ -43,20 +24,13 @@ var (
 	db *pgx.ConnPool
 )
 
-var (
-	listenAddr = flag.String("listenAddr", ":8080", "Address to listen to")
-	prefork    = flag.Bool("prefork", false, "use prefork")
-	child      = flag.Bool("child", false, "is child proc")
-)
-
 func main() {
 	flag.Parse()
 
 	var err error
 
-	// initialize the connection pool
 	dbConns := maxConnectionCount
-	if *prefork {
+	if *common.Prefork {
 		dbConns = (maxConnectionCount + runtime.NumCPU() - 1) / runtime.NumCPU()
 	}
 	if db, err = initDatabase("localhost", "benchmarkdbuser", "benchmarkdbpass", "hello_world", 5432, dbConns); err != nil {
@@ -67,7 +41,7 @@ func main() {
 		Handler: mainHandler,
 		Name:    "go",
 	}
-	ln := getListener()
+	ln := common.GetListener()
 	if err = s.Serve(ln); err != nil {
 		log.Fatalf("Error when serving incoming connections: %s", err)
 	}
@@ -77,9 +51,9 @@ func mainHandler(ctx *fasthttp.RequestCtx) {
 	path := ctx.Path()
 	switch string(path) {
 	case "/plaintext":
-		plaintextHandler(ctx)
+		common.PlaintextHandler(ctx)
 	case "/json":
-		jsonHandler(ctx)
+		common.JSONHandler(ctx)
 	case "/db":
 		dbHandler(ctx)
 	case "/queries":
@@ -93,40 +67,21 @@ func mainHandler(ctx *fasthttp.RequestCtx) {
 	}
 }
 
-// Test 1: JSON serialization
-func jsonHandler(ctx *fasthttp.RequestCtx) {
-	r := jsonResponsePool.Get().(*JSONResponse)
-	r.Message = "Hello, World!"
-	jsonMarshal(ctx, r)
-	jsonResponsePool.Put(r)
-}
-
-var jsonResponsePool = &sync.Pool{
-	New: func() interface{} {
-		return &JSONResponse{}
-	},
-}
-
-// Test 2: Single database query
 func dbHandler(ctx *fasthttp.RequestCtx) {
-	var w World
+	var w common.World
 	fetchRandomWorld(&w)
-	jsonMarshal(ctx, &w)
+	common.JSONMarshal(ctx, &w)
 }
 
-// Test 3: Multiple database queries
 func queriesHandler(ctx *fasthttp.RequestCtx) {
-	n := getQueriesCount(ctx)
-
-	worlds := make([]World, n)
+	n := common.GetQueriesCount(ctx)
+	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
 		fetchRandomWorld(&worlds[i])
 	}
-
-	jsonMarshal(ctx, worlds)
+	common.JSONMarshal(ctx, worlds)
 }
 
-// Test 4: Fortunes
 func fortuneHandler(ctx *fasthttp.RequestCtx) {
 	rows, err := db.Query("fortuneSelectStmt")
 	if err != nil {
@@ -144,25 +99,24 @@ func fortuneHandler(ctx *fasthttp.RequestCtx) {
 	rows.Close()
 	fortunes = append(fortunes, templates.Fortune{Message: "Additional fortune added at request time."})
 
-	sort.Sort(FortunesByMessage(fortunes))
+	sort.Sort(common.FortunesByMessage(fortunes))
 
 	ctx.SetContentType("text/html; charset=utf-8")
 	templates.WriteFortunePage(ctx, fortunes)
 }
 
-// Test 5: Database updates
 func updateHandler(ctx *fasthttp.RequestCtx) {
-	n := getQueriesCount(ctx)
+	n := common.GetQueriesCount(ctx)
 
-	worlds := make([]World, n)
+	worlds := make([]common.World, n)
 	for i := 0; i < n; i++ {
 		w := &worlds[i]
 		fetchRandomWorld(w)
-		w.RandomNumber = int32(randomWorldNum())
+		w.RandomNumber = int32(common.RandomWorldNum())
 	}
 
 	// sorting is required for insert deadlock prevention.
-	sort.Sort(WorldsByID(worlds))
+	sort.Sort(common.WorldsByID(worlds))
 	txn, err := db.Begin()
 	if err != nil {
 		log.Fatalf("Error starting transaction: %s", err)
@@ -178,56 +132,16 @@ func updateHandler(ctx *fasthttp.RequestCtx) {
 		log.Fatalf("Error when commiting world rows: %s", err)
 	}
 
-	jsonMarshal(ctx, worlds)
-}
-
-// Test 6: Plaintext
-func plaintextHandler(ctx *fasthttp.RequestCtx) {
-	ctx.SetContentType("text/plain")
-	ctx.WriteString("Hello, World!")
+	common.JSONMarshal(ctx, worlds)
 }
 
-func jsonMarshal(ctx *fasthttp.RequestCtx, v interface{}) {
-	ctx.SetContentType("application/json")
-	if err := json.NewEncoder(ctx).Encode(v); err != nil {
-		log.Fatalf("error in json.Encoder.Encode: %s", err)
-	}
-}
-
-func fetchRandomWorld(w *World) {
-	n := randomWorldNum()
-
+func fetchRandomWorld(w *common.World) {
+	n := common.RandomWorldNum()
 	if err := db.QueryRow("worldSelectStmt", n).Scan(&w.Id, &w.RandomNumber); err != nil {
 		log.Fatalf("Error scanning world row: %s", err)
 	}
 }
 
-func randomWorldNum() int {
-	return rand.Intn(worldRowCount) + 1
-}
-
-func getQueriesCount(ctx *fasthttp.RequestCtx) int {
-	n := ctx.QueryArgs().GetUintOrZero("queries")
-	if n < 1 {
-		n = 1
-	} else if n > 500 {
-		n = 500
-	}
-	return n
-}
-
-type FortunesByMessage []templates.Fortune
-
-func (s FortunesByMessage) Len() int           { return len(s) }
-func (s FortunesByMessage) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
-func (s FortunesByMessage) Less(i, j int) bool { return s[i].Message < s[j].Message }
-
-type WorldsByID []World
-
-func (w WorldsByID) Len() int           { return len(w) }
-func (w WorldsByID) Swap(i, j int)      { w[i], w[j] = w[j], w[i] }
-func (w WorldsByID) Less(i, j int) bool { return w[i].Id < w[j].Id }
-
 func mustPrepare(db *pgx.Conn, name, query string) *pgx.PreparedStatement {
 	stmt, err := db.Prepare(name, query)
 	if err != nil {
@@ -236,43 +150,6 @@ func mustPrepare(db *pgx.Conn, name, query string) *pgx.PreparedStatement {
 	return stmt
 }
 
-func getListener() net.Listener {
-	if !*prefork {
-		runtime.GOMAXPROCS(runtime.NumCPU())
-		ln, err := net.Listen("tcp4", *listenAddr)
-		if err != nil {
-			log.Fatal(err)
-		}
-		return ln
-	}
-
-	if !*child {
-		children := make([]*exec.Cmd, runtime.NumCPU())
-		for i := range children {
-			children[i] = exec.Command(os.Args[0], "-prefork", "-child")
-			children[i].Stdout = os.Stdout
-			children[i].Stderr = os.Stderr
-			if err := children[i].Start(); err != nil {
-				log.Fatal(err)
-			}
-		}
-		for _, ch := range children {
-			if err := ch.Wait(); err != nil {
-				log.Print(err)
-			}
-		}
-		os.Exit(0)
-		panic("unreachable")
-	}
-
-	runtime.GOMAXPROCS(1)
-	ln, err := reuseport.Listen("tcp4", *listenAddr)
-	if err != nil {
-		log.Fatal(err)
-	}
-	return ln
-}
-
 func initDatabase(dbHost string, dbUser string, dbPass string, dbName string, dbPort uint16, maxConnectionsInPool int) (*pgx.ConnPool, error) {
 
 	var successOrFailure string = "OK"
@@ -304,8 +181,8 @@ func initDatabase(dbHost string, dbUser string, dbPass string, dbName string, db
 		log.Println("Connecting to database ", dbName, " as user ", dbUser, ": ", successOrFailure)
 
 		log.Println("Fetching one record to test if db connection is valid...")
-		var w World
-		n := randomWorldNum()
+		var w common.World
+		n := common.RandomWorldNum()
 		if errPing := connPool.QueryRow("worldSelectStmt", n).Scan(&w.Id, &w.RandomNumber); errPing != nil {
 			log.Fatalf("Error scanning world row: %s", errPing)
 		}
@@ -315,5 +192,4 @@ func initDatabase(dbHost string, dbUser string, dbPass string, dbName string, db
 	fmt.Println("--------------------------------------------------------------------------------------------")
 
 	return connPool, err
-
 }

+ 3 - 0
frameworks/Go/fasthttp/src/templates/aux.go

@@ -0,0 +1,3 @@
+package templates
+
+//go:generate qtc

+ 0 - 0
frameworks/Go/fasthttp-postgresql/src/templates/fortune.qtpl → frameworks/Go/fasthttp/src/templates/fortune.qtpl


+ 0 - 3
frameworks/Go/go-std-mongodb/README.md

@@ -1,3 +0,0 @@
-# Go MongoDB Benchmarking Test
-
-This is the Go portion of a [benchmarking test suite](../), which uses MongoDB as its database.

+ 0 - 28
frameworks/Go/go-std-mongodb/benchmark_config.json

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

+ 0 - 6
frameworks/Go/go-std-mongodb/source_code

@@ -1,6 +0,0 @@
-./go/src/
-./go/src/hello
-./go/src/hello/hello.go
-./go/templates/
-./go/templates/fortune.html
-./go/templates/layout.html

+ 0 - 14
frameworks/Go/go-std-mongodb/templates/fortune.html

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

+ 0 - 9
frameworks/Go/go-std-mongodb/templates/layout.html

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

+ 0 - 2
frameworks/Go/go-std-mysql/setup.bat

@@ -1,2 +0,0 @@
-set GOPATH=C:\FrameworkBenchmarks\go
-go run src\hello\hello.go

+ 0 - 7
frameworks/Go/go-std-mysql/setup.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends go
-
-go get ./...
-
-go run src/hello/hello.go &

+ 0 - 7
frameworks/Go/go-std-mysql/setup_prefork.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends go
-
-go get ./...
-
-go run src/hello/hello.go -prefork &

+ 0 - 3
frameworks/Go/go-std-mysql/source_code

@@ -1,3 +0,0 @@
-./go/src/
-./go/src/hello
-./go/src/hello/hello.go

+ 0 - 26
frameworks/Go/go-std-postgresql/benchmark_config.json

@@ -1,26 +0,0 @@
-{
-  "framework": "go-std-postgresql",
-  "tests": [{
-    "default": {
-      "setup_file": "setup",
-      "db_url": "/db",
-      "query_url": "/queries?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Platform",
-      "database": "Postgres",
-      "framework": "go",
-      "language": "Go",
-      "orm": "Raw",
-      "platform": "Go",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "go-std-postgresql",
-      "notes": "",
-      "versus": "go"
-    }
-  }]
-}

+ 0 - 7
frameworks/Go/go-std-postgresql/setup.sh

@@ -1,7 +0,0 @@
-#!/bin/bash
-
-fw_depends go
-
-go get ./...
-
-go run src/hello/hello.go &

+ 0 - 3
frameworks/Go/go-std-postgresql/source_code

@@ -1,3 +0,0 @@
-./go/src/
-./go/src/hello
-./go/src/hello/hello.go

+ 2 - 2
frameworks/Go/go-std-mysql/README.md → frameworks/Go/go-std/README.md

@@ -1,13 +1,13 @@
 # Go Benchmarking Test
 
-This is the go portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
+This is the Go portion of a [benchmarking test suite](../) comparing a variety of web development platforms.
 
 ### JSON Encoding Test
 * [JSON test source](src/hello/hello.go)
 
 ## Versions
 
-* [Go 1.2rc3](http://golang.org/)
+* [Go 1.6](http://golang.org/)
 
 ## Test URLs
 

+ 45 - 3
frameworks/Go/go-std-mysql/benchmark_config.json → frameworks/Go/go-std/benchmark_config.json

@@ -20,7 +20,7 @@
       "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "go-std-mysql",
+      "display_name": "go-mysql",
       "notes": "",
       "versus": "go"
     },
@@ -41,7 +41,7 @@
       "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "go-std-mysql-interpolate",
+      "display_name": "go-mysql-interpolate",
       "notes": "",
       "versus": "go"
     },
@@ -64,7 +64,49 @@
       "webserver": "None",
       "os": "Linux",
       "database_os": "Linux",
-      "display_name": "go-std-prefork-mysql",
+      "display_name": "go-mysql-prefork",
+      "notes": "",
+      "versus": "go"
+    },
+    "mongo": {
+      "setup_file": "setup_mongo",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "MongoDB",
+      "framework": "go",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "go-mongodb",
+      "notes": "mongodb implementation for go net/http",
+      "versus": "go"
+    },
+    "postgres": {
+      "setup_file": "setup_postgres",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortune",
+      "update_url": "/update?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Postgres",
+      "framework": "go",
+      "language": "Go",
+      "orm": "Raw",
+      "platform": "Go",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "go-postgresql",
       "notes": "",
       "versus": "go"
     }

+ 24 - 21
frameworks/Go/go-std-mongodb/src/hello/hello.go → frameworks/Go/go-std/hello_mongo.go

@@ -2,25 +2,44 @@ package main
 
 import (
 	"encoding/json"
-	"gopkg.in/mgo.v2"
-	"gopkg.in/mgo.v2/bson"
 	"html/template"
 	"log"
 	"math/rand"
 	"net/http"
 	"sort"
 	"strconv"
+
+	"gopkg.in/mgo.v2"
+	"gopkg.in/mgo.v2/bson"
 )
 
 const (
 	connectionString = "localhost"
-	helloWorldString = "Hello, world!"
 	worldRowCount    = 10000
+	fortuneHTML      = `<!DOCTYPE html>
+<html>
+<head>
+<title>Fortunes</title>
+</head>
+<body>
+<table>
+<tr>
+<th>id</th>
+<th>message</th>
+</tr>
+{{range .}}
+<tr>
+<td>{{.Id}}</td>
+<td>{{.Message}}</td>
+</tr>
+{{end}}
+</table>
+</body>
+</html>`
 )
 
 var (
-	tmpl            = template.Must(template.ParseFiles("templates/layout.html", "templates/fortune.html"))
-	helloWorldBytes = []byte(helloWorldString)
+	tmpl = template.Must(template.New("fortune.html").Parse(fortuneHTML))
 
 	database *mgo.Database
 	fortunes *mgo.Collection
@@ -66,22 +85,13 @@ func main() {
 	database = session.DB("hello_world")
 	worlds = database.C("world")
 	fortunes = database.C("fortune")
-	http.HandleFunc("/json", jsonHandler)
 	http.HandleFunc("/db", dbHandler)
 	http.HandleFunc("/fortune", fortuneHandler)
 	http.HandleFunc("/queries", queriesHandler)
 	http.HandleFunc("/update", updateHandler)
-	http.HandleFunc("/plaintext", plaintextHandler)
 	http.ListenAndServe(":8080", nil)
 }
 
-// Test 1: JSON serialization
-func jsonHandler(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "application/json")
-	w.Header().Set("Server", "go-mongodb")
-	json.NewEncoder(w).Encode(&Message{helloWorldString})
-}
-
 // Helper for random numbers
 func getRandomNumber() uint16 {
 	return uint16(rand.Intn(worldRowCount) + 1)
@@ -169,10 +179,3 @@ func updateHandler(w http.ResponseWriter, r *http.Request) {
 	w.Header().Set("Server", "Go")
 	json.NewEncoder(w).Encode(&world)
 }
-
-// Test 6: Plaintext
-func plaintextHandler(w http.ResponseWriter, r *http.Request) {
-	w.Header().Set("Content-Type", "text/plain")
-	w.Header().Set("Server", "go-mongodb")
-	w.Write(helloWorldBytes)
-}

+ 0 - 0
frameworks/Go/go-std-mysql/src/hello/hello.go → frameworks/Go/go-std/hello_mysql.go


+ 0 - 0
frameworks/Go/go-std-postgresql/src/hello/hello.go → frameworks/Go/go-std/hello_postgres.go


+ 0 - 0
frameworks/Go/go-std-mongodb/setup.bat → frameworks/Go/go-std/setup.bat


+ 7 - 0
frameworks/Go/go-std/setup.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends go
+
+go get github.com/go-sql-driver/mysql
+
+go run hello_mysql.go &

+ 2 - 3
frameworks/Go/go-std-mongodb/setup.sh → frameworks/Go/go-std/setup_mongo.sh

@@ -1,10 +1,9 @@
 #!/bin/bash
 
-sed -i 's|connectionString = "localhost"|connectionString = "'"${DBHOST}"'"|g' src/hello/hello.go
+sed -i 's|connectionString = "localhost"|connectionString = "'"${DBHOST}"'"|g' hello_mongo.go
 
 fw_depends go
 
 go get gopkg.in/mgo.v2
-go get ./...
 
-go run src/hello/hello.go &
+go run hello_mongo.go &

+ 7 - 0
frameworks/Go/go-std/setup_postgres.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends go
+
+go get github.com/lib/pq
+
+go run hello_postgres.go &

+ 7 - 0
frameworks/Go/go-std/setup_prefork.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends go
+
+go get github.com/go-sql-driver/mysql
+
+go run hello_mysql.go -prefork &

+ 3 - 0
frameworks/Go/go-std/source_code

@@ -0,0 +1,3 @@
+./hello_mysql.go
+./hello_mongo.go
+./hello_postgres.go

+ 0 - 1
frameworks/Go/revel-jet/.gitignore

@@ -1 +0,0 @@
-src/github.com/

+ 0 - 26
frameworks/Go/revel-jet/benchmark_config.json

@@ -1,26 +0,0 @@
-{
-  "framework": "revel-jet",
-  "tests": [{
-    "default": {
-      "setup_file": "setup",
-      "db_url": "/db",
-      "query_url": "/db?queries=",
-      "fortune_url": "/fortune",
-      "update_url": "/update?queries=",
-      "port": 8080,
-      "approach": "Realistic",
-      "classification": "Fullstack",
-      "database": "MySQL",
-      "framework": "revel",
-      "language": "Go",
-      "orm": "Raw",
-      "platform": "Go",
-      "webserver": "None",
-      "os": "Linux",
-      "database_os": "Linux",
-      "display_name": "revel-jet",
-      "notes": "",
-      "versus": "go"
-    }
-  }]
-}

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