Browse Source

some optimization, add redis test, use FIFO scheduling policy

stefanocasazza 9 years ago
parent
commit
d6c83b482f

+ 9 - 5
frameworks/C++/ULib/README.md

@@ -1,6 +1,6 @@
 #ULib Benchmarking Test
 #ULib Benchmarking Test
 
 
-This is the ULib portion of a [benchmarking test suite](https://github.com/TechEmpower/FrameworkBenchmarks) comparing a variety of web development platforms.
+This is the [ULib](http://stefanocasazza.github.io/ULib/) portion of a [benchmarking test suite](https://github.com/TechEmpower/FrameworkBenchmarks) comparing a variety of web development platforms.
 
 
 ### JSON Encoding Test
 ### JSON Encoding Test
 
 
@@ -8,19 +8,23 @@ This is the ULib portion of a [benchmarking test suite](https://github.com/TechE
 
 
 ### Data-Store/Database Mapping Test
 ### Data-Store/Database Mapping Test
 
 
-* [Database test source](src/db.usp)
+* [Database test source (SQL)](src/db.usp)
+* [Database test source (REDIS)](src/rdb.usp)
 
 
 ### Variable Query Test
 ### Variable Query Test
 
 
-* [Variable Query test source](src/query.usp)
+* [Variable Query test source (SQL)](src/query.usp)
+* [Variable Query test source (REDIS)](src/rquery.usp)
 
 
 ### Fortune Query Test
 ### Fortune Query Test
 
 
-* [Fortune Query test source](src/fortune.usp)
+* [Fortune Query test source (SQL)](src/fortune.usp)
+* [Fortune Query test source (REDIS)](src/rfortune.usp)
 
 
 ### Variable Query (update) Test
 ### Variable Query (update) Test
 
 
-* [Variable Query (update) test source](src/update.usp)
+* [Variable Query (update) test source (SQL)](src/update.usp)
+* [Variable Query (update) test source (REDIS)](src/rupdate.usp)
 
 
 ### Plaintext Test
 ### Plaintext Test
 
 

+ 22 - 1
frameworks/C++/ULib/benchmark_config.json

@@ -1,5 +1,5 @@
 {
 {
-  "framework": "ulib",
+  "framework": "ULib",
   "tests": [{
   "tests": [{
     "default": {
     "default": {
       "setup_file": "setup_plaintext",
       "setup_file": "setup_plaintext",
@@ -98,6 +98,27 @@
       "display_name": "ULib-sqlite",
       "display_name": "ULib-sqlite",
       "notes": "",
       "notes": "",
       "versus": ""
       "versus": ""
+    },
+    "redis": {
+      "setup_file": "setup_redis",
+      "db_url": "/rdb",
+      "query_url": "/rquery?queries=",
+      "fortune_url": "/rfortune",
+      "update_url": "/rupdate?queries=",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Platform",
+      "database": "Redis",
+      "framework": "ULib",
+      "language": "C++",
+      "orm": "Micro",
+      "platform": "ULib",
+      "webserver": "userver_tcp",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "ULib-redis",
+      "notes": "",
+      "versus": ""
     }
     }
   }]
   }]
 }
 }

+ 13 - 4
frameworks/C++/ULib/setup_json.sh

@@ -1,14 +1,23 @@
 #!/bin/bash
 #!/bin/bash
 
 
-export UMEMPOOL="56,0,0,40,150,-24,-13,-20,0"
-
 fw_depends ulib
 fw_depends ulib
 
 
+let "MAX_THREADS = MAX_THREADS + MAX_THREADS / 2"
+
 # 1. Change ULib Server (userver_tcp) configuration
 # 1. Change ULib Server (userver_tcp) configuration
-sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g"										$IROOT/ULib/benchmark.cfg
+sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g"									  $IROOT/ULib/benchmark.cfg
 sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g"								  $IROOT/ULib/benchmark.cfg
 sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g"								  $IROOT/ULib/benchmark.cfg
 sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"					  $IROOT/ULib/benchmark.cfg
 sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"					  $IROOT/ULib/benchmark.cfg
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 
 
 # 2. Start ULib Server (userver_tcp)
 # 2. Start ULib Server (userver_tcp)
-userver_tcp -c $IROOT/ULib/benchmark.cfg &
+export UMEMPOOL="56,0,0,40,150,-24,-13,-20,0"
+
+# Never use setcap inside of TRAVIS 
+[ "$TRAVIS" != "true" ] || { \
+if [ `ulimit -r` -eq 99 ]; then
+	sudo setcap cap_sys_nice,cap_sys_resource,cap_net_bind_service,cap_net_raw+eip $IROOT/ULib/bin/userver_tcp
+fi
+}
+
+$IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 18 - 9
frameworks/C++/ULib/setup_mysql.sh

@@ -1,16 +1,25 @@
 #!/bin/bash
 #!/bin/bash
 
 
-export ORM_DRIVER="mysql"
-export UMEMPOOL="146,0,0,90,150,-22,-12,-20,0"
-export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=hello_world"
-
 fw_depends ulib
 fw_depends ulib
 
 
-# 1. Change ULib Server configuration
-sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET -2|g"                  $IROOT/ULib/benchmark.cfg
-sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g"                 $IROOT/ULib/benchmark.cfg
-sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"            $IROOT/ULib/benchmark.cfg
+let "MAX_THREADS = MAX_THREADS + MAX_THREADS / 2"
+
+# 1. Change ULib Server (userver_tcp) configuration
+sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET -2|g"								  $IROOT/ULib/benchmark.cfg
+sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g"								  $IROOT/ULib/benchmark.cfg
+sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"					  $IROOT/ULib/benchmark.cfg
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 
 
 # 2. Start ULib Server (userver_tcp)
 # 2. Start ULib Server (userver_tcp)
-userver_tcp -c $IROOT/ULib/benchmark.cfg &
+export ORM_DRIVER="mysql"
+export UMEMPOOL="146,0,0,90,150,-22,-12,-20,0"
+export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=hello_world"
+
+# Never use setcap inside of TRAVIS 
+[ "$TRAVIS" != "true" ] || { \
+if [ `ulimit -r` -eq 99 ]; then
+	sudo setcap cap_sys_nice,cap_sys_resource,cap_net_bind_service,cap_net_raw+eip $IROOT/ULib/bin/userver_tcp
+fi
+}
+
+$IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 9 - 0
frameworks/C++/ULib/setup_plaintext.sh

@@ -2,6 +2,8 @@
 
 
 fw_depends ulib
 fw_depends ulib
 
 
+let "MAX_THREADS = MAX_THREADS + MAX_THREADS / 2"
+
 # 1. Change ULib Server (userver_tcp) configuration
 # 1. Change ULib Server (userver_tcp) configuration
 sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g"										$IROOT/ULib/benchmark.cfg
 sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g"										$IROOT/ULib/benchmark.cfg
 sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 16384|g"								$IROOT/ULib/benchmark.cfg
 sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 16384|g"								$IROOT/ULib/benchmark.cfg
@@ -11,4 +13,11 @@ sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 8000|g" $IROO
 # 2. Start ULib Server (userver_tcp)
 # 2. Start ULib Server (userver_tcp)
 export UMEMPOOL="982,0,0,36,9846,-24,-23,1727,1151"
 export UMEMPOOL="982,0,0,36,9846,-24,-23,1727,1151"
 
 
+# Never use setcap inside of TRAVIS 
+[ "$TRAVIS" != "true" ] || { \
+if [ `ulimit -r` -eq 99 ]; then
+	sudo setcap cap_sys_nice,cap_sys_resource,cap_net_bind_service,cap_net_raw+eip $IROOT/ULib/bin/userver_tcp
+fi
+}
+
 $IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &
 $IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 12 - 5
frameworks/C++/ULib/setup_postgres.sh

@@ -1,9 +1,5 @@
 #!/bin/bash
 #!/bin/bash
 
 
-export ORM_DRIVER="pgsql"
-export UMEMPOOL="146,0,0,90,150,-22,-12,-20,0"
-export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world client_encoding=UTF8"
-
 fw_depends ulib
 fw_depends ulib
 
 
 MAX_THREADS=$((2 * $MAX_THREADS))
 MAX_THREADS=$((2 * $MAX_THREADS))
@@ -15,4 +11,15 @@ sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"					  $IROOT/ULib/ben
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 
 
 # 2. Start ULib Server (userver_tcp)
 # 2. Start ULib Server (userver_tcp)
-userver_tcp -c $IROOT/ULib/benchmark.cfg &
+export ORM_DRIVER="pgsql"
+export UMEMPOOL="146,0,0,90,150,-22,-12,-20,0"
+export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass dbname=hello_world client_encoding=UTF8"
+
+# Never use setcap inside of TRAVIS 
+[ "$TRAVIS" != "true" ] || { \
+if [ `ulimit -r` -eq 99 ]; then
+	sudo setcap cap_sys_nice,cap_sys_resource,cap_net_bind_service,cap_net_raw+eip $IROOT/ULib/bin/userver_tcp
+fi
+}
+
+$IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 24 - 0
frameworks/C++/ULib/setup_redis.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+fw_depends ulib
+
+let "MAX_THREADS = MAX_THREADS + MAX_THREADS / 2"
+
+# 1. Change ULib Server (userver_tcp) configuration
+sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g"									  $IROOT/ULib/benchmark.cfg
+sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g"								  $IROOT/ULib/benchmark.cfg
+sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"					  $IROOT/ULib/benchmark.cfg
+sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
+
+# 2. Start ULib Server (userver_tcp)
+export UMEMPOOL="146,0,0,90,150,-22,-12,-20,0"
+export REDIS_HOST=$DBHOST
+
+# Never use setcap inside of TRAVIS 
+[ "$TRAVIS" != "true" ] || { \
+if [ `ulimit -r` -eq 99 ]; then
+	sudo setcap cap_sys_nice,cap_sys_resource,cap_net_bind_service,cap_net_raw+eip $IROOT/ULib/bin/userver_tcp
+fi
+}
+
+$IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 18 - 9
frameworks/C++/ULib/setup_sqlite.sh

@@ -1,16 +1,25 @@
 #!/bin/bash
 #!/bin/bash
 
 
-export ORM_DRIVER="sqlite"
-export UMEMPOOL="146,0,0,90,150,-22,-12,-20,0"
-export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=${ULIB_ROOT}/db/%.*s"
-
 fw_depends ulib
 fw_depends ulib
 
 
-# 1. Change ULib Server configuration
-sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g"                   $IROOT/ULib/benchmark.cfg
-sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g"                 $IROOT/ULib/benchmark.cfg
-sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"            $IROOT/ULib/benchmark.cfg
+let "MAX_THREADS = MAX_THREADS + MAX_THREADS / 2"
+
+# 1. Change ULib Server (userver_tcp) configuration
+sed -i "s|TCP_LINGER_SET .*|TCP_LINGER_SET 0|g"									  $IROOT/ULib/benchmark.cfg
+sed -i "s|LISTEN_BACKLOG .*|LISTEN_BACKLOG 256|g"								  $IROOT/ULib/benchmark.cfg
+sed -i "s|PREFORK_CHILD .*|PREFORK_CHILD ${MAX_THREADS}|g"					  $IROOT/ULib/benchmark.cfg
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 sed -i "s|CLIENT_FOR_PARALLELIZATION .*|CLIENT_FOR_PARALLELIZATION 100|g" $IROOT/ULib/benchmark.cfg
 
 
 # 2. Start ULib Server (userver_tcp)
 # 2. Start ULib Server (userver_tcp)
-userver_tcp -c ${IROOT}/ULib/benchmark.cfg &
+export ORM_DRIVER="sqlite"
+export UMEMPOOL="146,0,0,90,150,-22,-12,-20,0"
+export ORM_OPTION="host=${DBHOST} user=benchmarkdbuser password=benchmarkdbpass character-set=utf8 dbname=${IROOT}/ULib/db/%.*s"
+
+# Never use setcap inside of TRAVIS 
+[ "$TRAVIS" != "true" ] || { \
+if [ `ulimit -r` -eq 99 ]; then
+	sudo setcap cap_sys_nice,cap_sys_resource,cap_net_bind_service,cap_net_raw+eip $IROOT/ULib/bin/userver_tcp
+fi
+}
+
+$IROOT/ULib/bin/userver_tcp -c $IROOT/ULib/benchmark.cfg &

+ 4 - 0
frameworks/C++/ULib/source_code

@@ -1,8 +1,12 @@
 ./src/db.usp
 ./src/db.usp
+./src/rdb.usp
 ./src/world.h
 ./src/world.h
 ./src/json.usp
 ./src/json.usp
 ./src/fortune.h
 ./src/fortune.h
 ./src/query.usp
 ./src/query.usp
+./src/rquery.usp
 ./src/update.usp
 ./src/update.usp
+./src/rupdate.usp
 ./src/fortune.usp
 ./src/fortune.usp
+./src/rfortune.usp
 ./src/plaintext.usp
 ./src/plaintext.usp

+ 7 - 7
frameworks/C++/ULib/src/fortune.usp

@@ -6,7 +6,7 @@ TechEmpower Web Framework Benchmarks
 #include "fortune.h"
 #include "fortune.h"
 
 
 static Fortune*           pfortune;
 static Fortune*           pfortune;
-static UString*           pmessage;
+static Fortune*           pfortune2add;
 static UString*           pencoded;
 static UString*           pencoded;
 static UOrmSession*       psql_fortune;
 static UOrmSession*       psql_fortune;
 static UOrmStatement*     pstmt_fortune;
 static UOrmStatement*     pstmt_fortune;
@@ -30,9 +30,9 @@ static void usp_fork_fortune()
 
 
       pstmt_fortune->into(*pfortune);
       pstmt_fortune->into(*pfortune);
 
 
-      pencoded  = U_NEW(UString(100U));
-      pmessage  = U_NEW(U_STRING_FROM_CONSTANT("Additional fortune added at request time."));
-      pvfortune = U_NEW(UVector<Fortune*>);
+      pencoded     = U_NEW(UString(100U));
+      pvfortune    = U_NEW(UVector<Fortune*>);
+      pfortune2add = U_NEW(Fortune(0, U_STRING_FROM_CONSTANT("Additional fortune added at request time.")));
       }
       }
 }
 }
 
 
@@ -45,11 +45,11 @@ static void usp_end_fortune()
       {
       {
       delete pstmt_fortune;
       delete pstmt_fortune;
 
 
+      delete pencoded;
       delete psql_fortune;
       delete psql_fortune;
       delete pvfortune;
       delete pvfortune;
       delete pfortune;
       delete pfortune;
-      delete pmessage;
-      delete pencoded;
+      delete pfortune2add;
       }
       }
 }
 }
 #endif
 #endif
@@ -57,7 +57,7 @@ static void usp_end_fortune()
 <!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><!--#code
 <!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><!--#code
 pstmt_fortune->execute();
 pstmt_fortune->execute();
 
 
-     pvfortune->push_back(U_NEW(Fortune(0, *pmessage)));
+     pvfortune->push_back(U_NEW(Fortune(*pfortune2add)));
 do { pvfortune->push_back(U_NEW(Fortune(*pfortune))); } while (pstmt_fortune->nextRow());
 do { pvfortune->push_back(U_NEW(Fortune(*pfortune))); } while (pstmt_fortune->nextRow());
 
 
 pvfortune->sort(Fortune::cmp_obj);
 pvfortune->sort(Fortune::cmp_obj);

+ 12 - 5
frameworks/C++/ULib/src/query.usp

@@ -53,9 +53,9 @@ static void usp_end_query()
       delete pvworld_query;
       delete pvworld_query;
       delete  pworld_query;
       delete  pworld_query;
 
 
-#   ifndef AS_cpoll_cppsp_DO
+#  ifndef AS_cpoll_cppsp_DO
       delete pvalue;
       delete pvalue;
-#   endif
+#  endif
       }
       }
 }
 }
 #endif
 #endif
@@ -67,10 +67,17 @@ queries;
 Content-Type: application/json; charset=UTF-8
 Content-Type: application/json; charset=UTF-8
 -->
 -->
 <!--#code
 <!--#code
-int i = 0, num_queries = queries.strtol();
+int i = 0, num_queries;
+const char* ptr = queries.data();
 
 
-     if (num_queries <   1) num_queries = 1;
-else if (num_queries > 500) num_queries = 500;
+if (u__isdigit(*ptr) == false) num_queries = 1;
+else
+   {
+   num_queries = u_strtoul(ptr, queries.end());
+
+        if (num_queries <   1) num_queries = 1;
+   else if (num_queries > 500) num_queries = 500;
+   }
 
 
 #ifdef AS_cpoll_cppsp_DO
 #ifdef AS_cpoll_cppsp_DO
 USP_PUTS_CHAR('[');
 USP_PUTS_CHAR('[');

+ 74 - 0
frameworks/C++/ULib/src/rdb.usp

@@ -0,0 +1,74 @@
+<!--#
+Test type 2: Single database query
+TechEmpower Web Framework Benchmarks
+-->
+<!--#declaration
+#include "world.h"
+
+static World* pworld;
+static UREDISClient_Base* rc;
+
+#ifndef AS_cpoll_cppsp_DO
+static UValue* pvalue;
+#endif
+
+static void usp_fork_rdb()
+{
+   U_TRACE(5, "::usp_fork_rdb()")
+
+   rc = U_NEW(UREDISClient<UTCPSocket>);
+
+   if (rc->connect() == false)
+      {
+      U_WARNING("usp_fork_rdb(): %V", rc->UClient_Base::getResponse().rep);
+
+      return;
+      }
+
+   pworld = U_NEW(World);
+
+#ifndef AS_cpoll_cppsp_DO
+   pvalue = U_NEW(UValue(OBJECT_VALUE));
+#endif
+}
+
+#ifdef DEBUG
+static void usp_end_rdb()
+{
+   U_TRACE(5, "::usp_end_rdb()")
+
+   delete rc;
+
+   if (pworld)
+      {
+      delete pworld;
+
+#  ifndef AS_cpoll_cppsp_DO
+      delete pvalue;
+#  endif
+      }
+}
+#endif
+-->
+<!--#header
+Content-Type: application/json; charset=UTF-8
+-->
+<!--#code
+UStringRep* rep;
+
+u_put_unalignedp32(u_buffer,   U_MULTICHAR_CONSTANT32('w','o','r','l'));
+u_put_unalignedp16(u_buffer+4, U_MULTICHAR_CONSTANT16('d',':'));
+
+(void) rc->get(u_buffer, 6+u_num2str32(u_buffer+6, pworld->id = u_get_num_random(10000)));
+
+rep = rc->vitem[0].rep;
+
+pworld->randomNumber = u_strtoul(rep->data(), rep->end());
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PRINTF_ADD("{\"id\":%u,\"randomNumber\":%v}", pworld->id, rep);
+#else
+USP_JSON_stringify(*pvalue, World, *pworld);
+pvalue->clear();
+#endif
+-->

+ 73 - 0
frameworks/C++/ULib/src/rfortune.usp

@@ -0,0 +1,73 @@
+<!--#
+Test type 4: Fortunes
+TechEmpower Web Framework Benchmarks
+-->
+<!--#declaration
+#include "fortune.h"
+
+static UString* pencoded;
+static UREDISClient_Base* rc;
+static Fortune* pfortune2add;
+static UVector<Fortune*>* pvfortune;
+
+static void usp_fork_rfortune()
+{
+   U_TRACE(5, "::usp_fork_rfortune()")
+
+   rc = U_NEW(UREDISClient<UTCPSocket>);
+
+   if (rc->connect() == false)
+      {
+      U_WARNING("usp_fork_rfortune(): %V", rc->UClient_Base::getResponse().rep);
+
+      return;
+      }
+
+   pencoded     = U_NEW(UString(100U));
+   pvfortune    = U_NEW(UVector<Fortune*>);
+   pfortune2add = U_NEW(Fortune(0, U_STRING_FROM_CONSTANT("Additional fortune added at request time.")));
+}
+
+#ifdef DEBUG
+static void usp_end_rfortune()
+{
+   U_TRACE(5, "::usp_end_rfortune()")
+
+   delete rc;
+
+   if (pencoded)
+      {
+      delete pencoded;
+      delete pvfortune;
+      delete pfortune2add;
+      }
+}
+#endif
+-->
+<!doctype html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr><!--#code
+uint32_t i, n;
+
+(void) rc->lrange(U_CONSTANT_TO_PARAM("fortunes 0 -1"));
+
+pvfortune->push_back(U_NEW(Fortune(*pfortune2add)));
+
+for (i = 0, n = rc->vitem.size(); i < n; ++i) pvfortune->push_back(U_NEW(Fortune(i+1, rc->vitem[i])));
+
+pvfortune->sort(Fortune::cmp_obj);
+
+for (i = 0, ++n; i < n; ++i)
+   {
+   Fortune* elem = (*pvfortune)[i];
+
+   UXMLEscape::encode(elem->message, *pencoded);
+
+   USP_PRINTF_ADD(
+      "<tr>"
+      "<td>%u</td>"
+      "<td>%v</td>"
+      "</tr>",
+      elem->id, pencoded->rep);
+   }
+
+pvfortune->clear();
+--></table></body></html>

+ 118 - 0
frameworks/C++/ULib/src/rquery.usp

@@ -0,0 +1,118 @@
+<!--#
+Test type 3: Multiple database queries
+TechEmpower Web Framework Benchmarks
+-->
+<!--#declaration
+#include "world.h"
+
+static UREDISClient_Base* rc;
+static UVector<World*>* pvworld;
+
+#ifndef AS_cpoll_cppsp_DO
+static UValue* pvalue;
+#endif
+
+static void usp_fork_rquery()
+{
+   U_TRACE(5, "::usp_fork_rquery()")
+
+   rc = U_NEW(UREDISClient<UTCPSocket>);
+
+   if (rc->connect() == false)
+      {
+      U_WARNING("usp_fork_rquery(): %V", rc->UClient_Base::getResponse().rep);
+
+      return;
+      }
+
+   pvworld = U_NEW(UVector<World*>(500));
+
+#ifndef AS_cpoll_cppsp_DO
+   pvalue = U_NEW(UValue(ARRAY_VALUE));
+#endif
+}
+
+#ifdef DEBUG
+static void usp_end_rquery()
+{
+   U_TRACE(5, "::usp_end_rquery()")
+
+   delete rc;
+
+   if (pvworld)
+      {
+      delete pvworld;
+
+#  ifndef AS_cpoll_cppsp_DO
+      delete pvalue;
+#  endif
+      }
+}
+#endif
+-->
+<!--#args
+queries;
+-->
+<!--#header
+Content-Type: application/json; charset=UTF-8
+-->
+<!--#code
+World* pworld;
+UStringRep* rep;
+int i, num_queries;
+char* pbuffer = u_buffer;
+const char* ptr = queries.data();
+
+if (u__isdigit(*ptr) == false) num_queries = 1;
+else
+   {
+   num_queries = u_strtoul(ptr, queries.end());
+
+        if (num_queries <   1) num_queries = 1;
+   else if (num_queries > 500) num_queries = 500;
+   }
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR('[');
+#endif
+
+for (i = 0; i < num_queries; ++i)
+   {
+   pvworld->push_back(pworld = U_NEW(World));
+
+   u_put_unalignedp64(pbuffer, U_MULTICHAR_CONSTANT64(' ','w','o','r','l','d',':','\0'));
+
+   pbuffer += 7+u_num2str32(pbuffer+7, pworld->id = u_get_num_random(10000));
+   }
+
+(void) rc->mget(u_buffer, pbuffer-u_buffer);
+
+i = 0;
+
+while (true)
+   {
+   pworld = pvworld->at(i);
+
+   rep = rc->vitem[i].rep;
+
+   pworld->randomNumber = u_strtoul(rep->data(), rep->end());
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PRINTF("{\"id\":%u,\"randomNumber\":%v}", pworld->id, rep);
+#endif
+
+   if (++i == num_queries) break;
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PUTS_CHAR(',');
+#endif
+   }
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR(']');
+#else
+USP_JSON_stringify(*pvalue, UVector<World*>, *pvworld);
+pvalue->clear();
+#endif
+pvworld->clear();
+-->

+ 122 - 0
frameworks/C++/ULib/src/rupdate.usp

@@ -0,0 +1,122 @@
+<!--#
+Test type 5: Database updates
+TechEmpower Web Framework Benchmarks
+-->
+<!--#declaration
+#include "world.h"
+
+static UREDISClient_Base* rc;
+static UVector<World*>* pvworld;
+
+#ifndef AS_cpoll_cppsp_DO
+static UValue* pvalue;
+#endif
+
+static void usp_fork_rupdate()
+{
+   U_TRACE(5, "::usp_fork_rupdate()")
+
+   rc = U_NEW(UREDISClient<UTCPSocket>);
+
+   if (rc->connect() == false)
+      {
+      U_WARNING("usp_fork_rupdate(): %V", rc->UClient_Base::getResponse().rep);
+
+      return;
+      }
+
+   pvworld = U_NEW(UVector<World*>(500));
+
+#ifndef AS_cpoll_cppsp_DO
+   pvalue = U_NEW(UValue(ARRAY_VALUE));
+#endif
+}
+
+#ifdef DEBUG
+static void usp_end_rupdate()
+{
+   U_TRACE(5, "::usp_end_rupdate()")
+
+   delete rc;
+
+   if (pvworld)
+      {
+      delete pvworld;
+
+#  ifndef AS_cpoll_cppsp_DO
+      delete pvalue;
+#  endif
+      }
+}
+#endif
+-->
+<!--#args
+queries;
+-->
+<!--#header
+Content-Type: application/json; charset=UTF-8
+-->
+<!--#code
+World* pworld;
+int i, num_queries;
+char* pbuffer = u_buffer;
+const char* ptr = queries.data();
+
+if (u__isdigit(*ptr) == false) num_queries = 1;
+else
+   {
+   num_queries = u_strtoul(ptr, queries.end());
+
+        if (num_queries <   1) num_queries = 1;
+   else if (num_queries > 500) num_queries = 500;
+   }
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR('[');
+#endif
+
+for (i = 0; i < num_queries; ++i)
+   {
+   pvworld->push_back(pworld = U_NEW(World));
+
+   u_put_unalignedp64(pbuffer, U_MULTICHAR_CONSTANT64(' ','w','o','r','l','d',':','\0'));
+
+   pbuffer += 7+u_num2str32(pbuffer+7, pworld->id = u_get_num_random(10000));
+   }
+
+(void) rc->mget(u_buffer, pbuffer-u_buffer);
+
+i = 0;
+pbuffer = u_buffer;
+
+while (true)
+   {
+   pworld = pvworld->at(i);
+
+   u_put_unalignedp64(pbuffer, U_MULTICHAR_CONSTANT64(' ','w','o','r','l','d',':','\0'));
+
+   pbuffer += 7+u_num2str32(pbuffer+7, pworld->id);
+  *pbuffer  = ' ';
+   pbuffer += 1+u_num2str32(pbuffer+1, pworld->randomNumber = u_get_num_random(10000));
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PRINTF("{\"id\":%u,\"randomNumber\":%u}", pworld->id, pworld->randomNumber);
+#endif
+
+   if (++i == num_queries) break;
+
+#ifdef AS_cpoll_cppsp_DO
+   USP_PUTS_CHAR(',');
+#endif
+   }
+
+(void) rc->mset(u_buffer, pbuffer-u_buffer);
+
+#ifdef AS_cpoll_cppsp_DO
+USP_PUTS_CHAR(']');
+#else
+USP_JSON_stringify(*pvalue, UVector<World*>, *pvworld);
+pvalue->clear();
+#endif
+pvworld->clear();
+-->

+ 10 - 3
frameworks/C++/ULib/src/update.usp

@@ -75,10 +75,17 @@ queries;
 Content-Type: application/json; charset=UTF-8
 Content-Type: application/json; charset=UTF-8
 -->
 -->
 <!--#code
 <!--#code
-int i = 0, num_queries = queries.strtol();
+int i = 0, num_queries;
+const char* ptr = queries.data();
 
 
-     if (num_queries <   1) num_queries = 1;
-else if (num_queries > 500) num_queries = 500;
+if (u__isdigit(*ptr) == false) num_queries = 1;
+else
+   {
+   num_queries = u_strtoul(ptr, queries.end());
+
+        if (num_queries <   1) num_queries = 1;
+   else if (num_queries > 500) num_queries = 500;
+   }
 
 
 #ifdef AS_cpoll_cppsp_DO
 #ifdef AS_cpoll_cppsp_DO
 USP_PUTS_CHAR('[');
 USP_PUTS_CHAR('[');

+ 9 - 3
toolset/setup/linux/frameworks/ulib.sh

@@ -21,6 +21,13 @@ fi
 # TODO: This should already be installed and unnecessary.
 # TODO: This should already be installed and unnecessary.
 sudo apt-get install -y postgresql-server-dev-all
 sudo apt-get install -y postgresql-server-dev-all
 
 
+# make use of FIFO scheduling policy possible
+type setcap >/dev/null 2>/dev/null
+
+if [ $? -ne 0 ]; then
+   sudo apt-get install -y libcap2-bin
+fi
+
 # Add a simple configuration file to it
 # Add a simple configuration file to it
 cd $ULIB_ROOT
 cd $ULIB_ROOT
 if [ ! -f "benchmark.cfg" ]; then
 if [ ! -f "benchmark.cfg" ]; then
@@ -80,7 +87,7 @@ make install
 
 
 # 3. Compile usp pages for benchmark
 # 3. Compile usp pages for benchmark
 cd ../../src/ulib/net/server/plugin/usp
 cd ../../src/ulib/net/server/plugin/usp
-make db.la fortune.la json.la plaintext.la query.la update.la
+make db.la fortune.la json.la plaintext.la query.la update.la rdb.la rquery.la rupdate.la rfortune.la
 
 
 # Check that compilation worked
 # Check that compilation worked
 if [ ! -e .libs/db.so ]; then
 if [ ! -e .libs/db.so ]; then
@@ -88,9 +95,8 @@ if [ ! -e .libs/db.so ]; then
 fi
 fi
 
 
 mkdir -p $ULIB_DOCUMENT_ROOT
 mkdir -p $ULIB_DOCUMENT_ROOT
-cp .libs/db.so .libs/fortune.so .libs/json.so .libs/plaintext.so .libs/query.so .libs/update.so $ULIB_DOCUMENT_ROOT
+cp .libs/db.so .libs/fortune.so .libs/json.so .libs/plaintext.so .libs/query.so .libs/update.so .libs/rdb.so .libs/rquery.so .libs/rupdate.so .libs/rfortune.so $ULIB_DOCUMENT_ROOT
 
 
-echo 'export UMEMPOOL="136,0,0,85,1160,155,-17,-22,40"' > $IROOT/ulib.installed
 echo "export ULIB_VERSION=${ULIB_VERSION}" >> $IROOT/ulib.installed
 echo "export ULIB_VERSION=${ULIB_VERSION}" >> $IROOT/ulib.installed
 echo "export ULIB_ROOT=${ULIB_ROOT}" >> $IROOT/ulib.installed
 echo "export ULIB_ROOT=${ULIB_ROOT}" >> $IROOT/ulib.installed
 echo "export ULIB_DOCUMENT_ROOT=${ULIB_DOCUMENT_ROOT}" >> $IROOT/ulib.installed
 echo "export ULIB_DOCUMENT_ROOT=${ULIB_DOCUMENT_ROOT}" >> $IROOT/ulib.installed