Browse Source

cutelyst fixes for round 13 (#2255)

Nginx was using only one worker, now with auto it
will have the same number as processors available,
and uWSGI HTTP parser does not support keep-alive
which on poor Azure connection led to 7 req/s
so replacing it with our own HTTP server which supports
keep-alive and pipelining, and adding threaded tests.
Daniel Nicoletti 9 years ago
parent
commit
e332c36012

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

+ 1 - 1
toolset/setup/linux/frameworks/cutelyst.sh

@@ -1,6 +1,6 @@
 #!/bin/bash
 #!/bin/bash
 
 
-CUTELYST_VER=0.12.0
+CUTELYST_VER=0.13.3
 RETCODE=$(fw_exists ${IROOT}/cutelyst.installed)
 RETCODE=$(fw_exists ${IROOT}/cutelyst.installed)
 [ ! "$RETCODE" == 0 ] || { \
 [ ! "$RETCODE" == 0 ] || { \
   source $IROOT/cutelyst.installed
   source $IROOT/cutelyst.installed