Browse Source

Update Drogon to the latest version and make some optimizations (#4916)

An Tao 6 years ago
parent
commit
8bfed7edac
26 changed files with 319 additions and 238 deletions
  1. 1 1
      frameworks/C++/drogon/drogon-raw.dockerfile
  2. 1 1
      frameworks/C++/drogon/drogon.dockerfile
  3. 2 2
      frameworks/C++/drogon/drogon_benchmark/config-raw.json
  4. 2 2
      frameworks/C++/drogon/drogon_benchmark/config.json
  5. 21 18
      frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrl.cc
  6. 7 5
      frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrl.h
  7. 8 4
      frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrlRaw.cc
  8. 7 5
      frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrlRaw.h
  9. 32 26
      frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrl.cc
  10. 6 4
      frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrl.h
  11. 33 27
      frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrlRaw.cc
  12. 6 4
      frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrlRaw.h
  13. 5 3
      frameworks/C++/drogon/drogon_benchmark/controllers/JsonCtrl.cc
  14. 7 5
      frameworks/C++/drogon/drogon_benchmark/controllers/JsonCtrl.h
  15. 3 2
      frameworks/C++/drogon/drogon_benchmark/controllers/PlaintextCtrl.cc
  16. 7 5
      frameworks/C++/drogon/drogon_benchmark/controllers/PlaintextCtrl.h
  17. 24 21
      frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrl.cc
  18. 5 3
      frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrl.h
  19. 27 14
      frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrlRaw.cc
  20. 7 5
      frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrlRaw.h
  21. 40 32
      frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrl.cc
  22. 5 3
      frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrl.h
  23. 44 35
      frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrlRaw.cc
  24. 7 5
      frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrlRaw.h
  25. 5 2
      frameworks/C++/drogon/drogon_benchmark/views/fortune.csp
  26. 7 4
      frameworks/C++/drogon/drogon_benchmark/views/fortune_raw.csp

+ 1 - 1
frameworks/C++/drogon/drogon-raw.dockerfile

@@ -34,7 +34,7 @@ RUN git clone https://github.com/an-tao/drogon
 
 WORKDIR $DROGON_ROOT
 
-RUN git checkout 32836a0fef0a9a1061ac92ef87bd269edb2e1734
+RUN git checkout d56b71c8a9b2b4bd0dd67052fe87c4768adfeb66
 
 RUN ./build.sh
 

+ 1 - 1
frameworks/C++/drogon/drogon.dockerfile

@@ -34,7 +34,7 @@ RUN git clone https://github.com/an-tao/drogon
 
 WORKDIR $DROGON_ROOT
 
-RUN git checkout 32836a0fef0a9a1061ac92ef87bd269edb2e1734
+RUN git checkout d56b71c8a9b2b4bd0dd67052fe87c4768adfeb66
 
 RUN ./build.sh
 

+ 2 - 2
frameworks/C++/drogon/drogon_benchmark/config-raw.json

@@ -34,7 +34,7 @@
         //any synchronous interface of it.
         "is_fast": true,
         //connection_number:1 by default
-        "connection_number": 1
+        "connection_number": 8
     }],
     "app": {
         //threads_num:the number of IO threads,1 by default, if the value is set to 0, the number of threads
@@ -137,7 +137,7 @@
         "idle_connection_timeout": 60,
         //server_header_field: Set the 'server' header field in each response sent by drogon,
         //empty string by default with which the 'server' header field is set to "Server: drogon/version string\r\n"
-        "server_header_field": "",
+        "server_header_field": "drogon",
         //keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection. 
         //After the maximum number of requests are made, the connection is closed.
         //The default value of 0 means no limit.

+ 2 - 2
frameworks/C++/drogon/drogon_benchmark/config.json

@@ -34,7 +34,7 @@
         //any synchronous interface of it.
         "is_fast": true,
         //connection_number:1 by default
-        "connection_number": 1
+        "connection_number": 8
     }],
     "app": {
         //threads_num:the number of IO threads,1 by default, if the value is set to 0, the number of threads
@@ -153,7 +153,7 @@
         "idle_connection_timeout": 60,
         //server_header_field: Set the 'server' header field in each response sent by drogon,
         //empty string by default with which the 'server' header field is set to "Server: drogon/version string\r\n"
-        "server_header_field": "",
+        "server_header_field": "dg",
         //keepalive_requests: Set the maximum number of requests that can be served through one keep-alive connection. 
         //After the maximum number of requests are made, the connection is closed.
         //The default value of 0 means no limit.

+ 21 - 18
frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrl.cc

@@ -6,28 +6,31 @@
 #include <time.h>
 using namespace drogon_model::hello_world;
 
-void DbCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback)
+void DbCtrl::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
-    //write your application logic here
+    // write your application logic here
     static std::once_flag once;
-    std::call_once(once, []() {
-        srand(time(NULL));
-    });
+    std::call_once(once, []() { srand(time(NULL)); });
     auto client = drogon::app().getFastDbClient();
 
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
     drogon::orm::Mapper<World> mapper(client);
     World::PrimaryKeyType id = rand() % 10000 + 1;
-    mapper.findByPrimaryKey(id,
-                            [callbackPtr](World w) {
-                                auto j = w.toJson();
-                                auto resp = HttpResponse::newHttpJsonResponse(j);
-                                (*callbackPtr)(resp);
-                            },
-                            [callbackPtr](const DrogonDbException &e) {
-                                Json::Value ret;
-                                ret["result"] = "error!";
-                                auto resp = HttpResponse::newHttpJsonResponse(ret);
-                                (*callbackPtr)(resp);
-                            });
+    mapper.findByPrimaryKey(
+        id,
+        [callbackPtr](World w) {
+            auto j = w.toJson();
+            auto resp = HttpResponse::newHttpJsonResponse(j);
+            (*callbackPtr)(resp);
+        },
+        [callbackPtr](const DrogonDbException &e) {
+            Json::Value ret;
+            ret["result"] = "error!";
+            auto resp = HttpResponse::newHttpJsonResponse(ret);
+            (*callbackPtr)(resp);
+        });
 }

+ 7 - 5
frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrl.h

@@ -1,12 +1,14 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class DbCtrl:public drogon::HttpSimpleController<DbCtrl>
+class DbCtrl : public drogon::HttpSimpleController<DbCtrl>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/db", Get);
+    // list path definitions here;
+    // PATH_ADD("/db", Get);
     PATH_LIST_END
 };

+ 8 - 4
frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrlRaw.cc

@@ -15,15 +15,19 @@ void DbCtrlRaw::asyncHandleHttpRequest(
     std::call_once(once, []() { srand(time(NULL)); });
     auto client = drogon::app().getFastDbClient();
     int id = rand() % 10000 + 1;
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
 
     *client << "select randomnumber from world where id=$1" << id >>
         [callbackPtr, id](const Result &rows) {
             auto resp = HttpResponse::newHttpResponse();
             char json[64];
-            sprintf(json, "{\"id\":%d,\"randomnumber\":%s}", id,
-                    rows[0]["randomnumber"].c_str());
-            resp->setBody(std::string(json));
+            auto size = sprintf(json,
+                                "{\"id\":%d,\"randomnumber\":%s}",
+                                id,
+                                rows[0]["randomnumber"].c_str());
+            resp->setBody(std::string(json, size));
             resp->setContentTypeCode(CT_APPLICATION_JSON);
             (*callbackPtr)(resp);
         } >>

+ 7 - 5
frameworks/C++/drogon/drogon_benchmark/controllers/DbCtrlRaw.h

@@ -1,12 +1,14 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class DbCtrlRaw:public drogon::HttpSimpleController<DbCtrlRaw>
+class DbCtrlRaw : public drogon::HttpSimpleController<DbCtrlRaw>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/db", Get);
+    // list path definitions here;
+    // PATH_ADD("/db", Get);
     PATH_LIST_END
 };

+ 32 - 26
frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrl.cc

@@ -3,34 +3,40 @@
 #include <algorithm>
 
 using namespace drogon_model::hello_world;
-void FortuneCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback)
+void FortuneCtrl::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
     auto client = drogon::app().getFastDbClient();
     drogon::orm::Mapper<Fortune> mapper(client);
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
 
-    mapper.findAll([callbackPtr](std::vector<Fortune> rows) {
-                        Fortune newRow;
-                        newRow.setId(0);
-                        newRow.setMessage("Additional fortune added at request time.");
-                        rows.emplace_back(std::move(newRow));
-                        std::sort(rows.begin(),
-                                  rows.end(),
-                                  [](const Fortune &f1, const Fortune &f2) -> bool {
-                                      if (f1.getValueOfMessage() < f2.getValueOfMessage())
-                                          return true;
-                                      else
-                                      {
-                                          return false;
-                                      }
-                                  });
-                        HttpViewData data;
-                        data.insert("rows",std::move(rows));
-                        auto resp=HttpResponse::newHttpViewResponse("fortune.csp",data);
-                        (*callbackPtr)(resp); },
-                   [callbackPtr](const DrogonDbException &err) {
-                       auto resp = HttpResponse::newHttpResponse();
-                       resp->setBody(std::string("error:") + err.base().what());
-                       (*callbackPtr)(resp);
-                   });
+    mapper.findAll(
+        [callbackPtr](std::vector<Fortune> rows) {
+            Fortune newRow;
+            newRow.setId(0);
+            newRow.setMessage("Additional fortune added at request time.");
+            rows.emplace_back(std::move(newRow));
+            std::sort(rows.begin(),
+                      rows.end(),
+                      [](const Fortune &f1, const Fortune &f2) -> bool {
+                          if (f1.getValueOfMessage() < f2.getValueOfMessage())
+                              return true;
+                          else
+                          {
+                              return false;
+                          }
+                      });
+            HttpViewData data;
+            data.insert("rows", std::move(rows));
+            auto resp = HttpResponse::newHttpViewResponse("fortune.csp", data);
+            (*callbackPtr)(resp);
+        },
+        [callbackPtr](const DrogonDbException &err) {
+            auto resp = HttpResponse::newHttpResponse();
+            resp->setBody(std::string("error:") + err.base().what());
+            (*callbackPtr)(resp);
+        });
 }

+ 6 - 4
frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrl.h

@@ -1,11 +1,13 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class FortuneCtrl:public drogon::HttpSimpleController<FortuneCtrl>
+class FortuneCtrl : public drogon::HttpSimpleController<FortuneCtrl>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
+    // list path definitions here;
     PATH_LIST_END
 };

+ 33 - 27
frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrlRaw.cc

@@ -3,33 +3,39 @@
 #include <algorithm>
 
 using namespace drogon_model::hello_world;
-void FortuneCtrlRaw::asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback)
+void FortuneCtrlRaw::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
     auto client = drogon::app().getFastDbClient();
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
 
-    *client << "select * from fortune where 1=$1"
-            << 1 >>
-        [callbackPtr](const Result &r) {
-            std::vector<std::pair<int, std::string>> rows;
-            for (auto row : r)
-            {
-                rows.emplace_back(row["id"].as<int>(), row["message"].as<std::string>());
-            }
-            rows.emplace_back(0, "Additional fortune added at request time.");
-            std::sort(rows.begin(), rows.end(), [](const std::pair<int, std::string> &p1, const std::pair<int, std::string> &p2) -> bool {
-                if (p1.second < p2.second)
-                    return true;
-                return false;
-            });
-            HttpViewData data;
-            data.insert("rows", std::move(rows));
-            auto resp = HttpResponse::newHttpViewResponse("fortune_raw.csp", data);
-            (*callbackPtr)(resp);
-        } >>
-        [callbackPtr](const DrogonDbException &err) {
-            auto resp = HttpResponse::newHttpResponse();
-            resp->setBody(std::string("error:") + err.base().what());
-            (*callbackPtr)(resp);
-        };
-}
+    *client << "select * from fortune where 1=$1" << 1 >> [callbackPtr](
+                                                              const Result &r) {
+        std::vector<std::pair<string_view, string_view>> rows;
+        for (auto const &row : r)
+        {
+            rows.emplace_back(row["id"].as<string_view>(),
+                              row["message"].as<string_view>());
+        }
+        rows.emplace_back("0", "Additional fortune added at request time.");
+        std::sort(rows.begin(),
+                  rows.end(),
+                  [](const std::pair<string_view, string_view> &p1,
+                     const std::pair<string_view, string_view> &p2) -> bool {
+                      if (p1.second < p2.second)
+                          return true;
+                      return false;
+                  });
+        HttpViewData data;
+        data.insert("rows", std::move(rows));
+        auto resp = HttpResponse::newHttpViewResponse("fortune_raw.csp", data);
+        (*callbackPtr)(resp);
+    } >> [callbackPtr](const DrogonDbException &err) {
+        auto resp = HttpResponse::newHttpResponse();
+        resp->setBody(std::string("error:") + err.base().what());
+        (*callbackPtr)(resp);
+    };
+}

+ 6 - 4
frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrlRaw.h

@@ -1,11 +1,13 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class FortuneCtrlRaw:public drogon::HttpSimpleController<FortuneCtrlRaw>
+class FortuneCtrlRaw : public drogon::HttpSimpleController<FortuneCtrlRaw>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
+    // list path definitions here;
     PATH_LIST_END
 };

+ 5 - 3
frameworks/C++/drogon/drogon_benchmark/controllers/JsonCtrl.cc

@@ -1,8 +1,10 @@
 #include "JsonCtrl.h"
-void JsonCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback)
+void JsonCtrl::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
     Json::Value ret;
-    ret["message"]="Hello, World!";
-    auto resp=HttpResponse::newHttpJsonResponse(ret);
+    ret["message"] = "Hello, World!";
+    auto resp = HttpResponse::newHttpJsonResponse(ret);
     callback(resp);
 }

+ 7 - 5
frameworks/C++/drogon/drogon_benchmark/controllers/JsonCtrl.h

@@ -1,12 +1,14 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class JsonCtrl:public drogon::HttpSimpleController<JsonCtrl>
+class JsonCtrl : public drogon::HttpSimpleController<JsonCtrl>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback)override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/json",Get);
+    // list path definitions here;
+    // PATH_ADD("/json",Get);
     PATH_LIST_END
 };

+ 3 - 2
frameworks/C++/drogon/drogon_benchmark/controllers/PlaintextCtrl.cc

@@ -3,7 +3,8 @@ void PlaintextCtrl::asyncHandleHttpRequest(const HttpRequestPtr& req, std::funct
 {
     auto resp = HttpResponse::newHttpResponse();
     resp->setBody("Hello, World!");
-    resp->setContentTypeCode(CT_TEXT_PLAIN);
-//    resp->setExpiredTime(0);
+    resp->setContentTypeCodeAndCustomString(CT_TEXT_PLAIN,
+                                            "Content-Type: text/plain\r\n");
+    //    resp->setExpiredTime(0);
     callback(resp);
 }

+ 7 - 5
frameworks/C++/drogon/drogon_benchmark/controllers/PlaintextCtrl.h

@@ -1,12 +1,14 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class PlaintextCtrl:public drogon::HttpSimpleController<PlaintextCtrl>
+class PlaintextCtrl : public drogon::HttpSimpleController<PlaintextCtrl>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback)override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/plaintext",Get);
+    // list path definitions here;
+    // PATH_ADD("/plaintext",Get);
     PATH_LIST_END
 };

+ 24 - 21
frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrl.cc

@@ -4,13 +4,13 @@
 
 using namespace drogon_model::hello_world;
 
-void QueriesCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback)
+void QueriesCtrl::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
-    //write your application logic here
+    // write your application logic here
     static std::once_flag once;
-    std::call_once(once, []() {
-        srand(time(NULL));
-    });
+    std::call_once(once, []() { srand(time(NULL)); });
     int queries = 1;
     auto &parameter = req->getParameter("queries");
     if (!parameter.empty())
@@ -23,7 +23,9 @@ void QueriesCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::functio
     }
     auto json = std::make_shared<Json::Value>();
     json->resize(0);
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
     auto counter = std::make_shared<int>(queries);
     auto client = app().getFastDbClient();
     drogon::orm::Mapper<World> mapper(client);
@@ -31,20 +33,21 @@ void QueriesCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::functio
     for (int i = 0; i < queries; i++)
     {
         World::PrimaryKeyType id = rand() % 10000 + 1;
-        mapper.findByPrimaryKey(id,
-                                [callbackPtr, counter, json](World w) mutable {
-                                    json->append(w.toJson());
-                                    (*counter)--;
-                                    if ((*counter) == 0)
-                                    {
-                                        (*callbackPtr)(HttpResponse::newHttpJsonResponse(*json));
-                                    }
-                                },
-                                [callbackPtr](const DrogonDbException &e) {
-                                    Json::Value ret;
-                                    ret["result"] = "error!";
-                                    auto resp = HttpResponse::newHttpJsonResponse(ret);
-                                    (*callbackPtr)(resp);
-                                });
+        mapper.findByPrimaryKey(
+            id,
+            [callbackPtr, counter, json](World w) mutable {
+                json->append(w.toJson());
+                (*counter)--;
+                if ((*counter) == 0)
+                {
+                    (*callbackPtr)(HttpResponse::newHttpJsonResponse(*json));
+                }
+            },
+            [callbackPtr](const DrogonDbException &e) {
+                Json::Value ret;
+                ret["result"] = "error!";
+                auto resp = HttpResponse::newHttpJsonResponse(ret);
+                (*callbackPtr)(resp);
+            });
     }
 }

+ 5 - 3
frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrl.h

@@ -4,9 +4,11 @@ using namespace drogon;
 class QueriesCtrl : public drogon::HttpSimpleController<QueriesCtrl>
 {
   public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
+    // list path definitions here;
+    // PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
     PATH_LIST_END
 };

+ 27 - 14
frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrlRaw.cc

@@ -1,12 +1,12 @@
 #include "QueriesCtrlRaw.h"
 using namespace drogon::orm;
-void QueriesCtrlRaw::asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback)
+void QueriesCtrlRaw::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
-    //write your application logic here
+    // write your application logic here
     static std::once_flag once;
-    std::call_once(once, []() {
-        srand(time(NULL));
-    });
+    std::call_once(once, []() { srand(time(NULL)); });
     int queries = 1;
     auto &parameter = req->getParameter("queries");
     if (!parameter.empty())
@@ -17,27 +17,40 @@ void QueriesCtrlRaw::asyncHandleHttpRequest(const HttpRequestPtr &req, std::func
         else if (queries < 1)
             queries = 1;
     }
-    auto json = std::make_shared<Json::Value>();
-    json->resize(0);
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
     auto counter = std::make_shared<int>(queries);
     auto client = app().getFastDbClient();
+    auto jsonStr = std::make_shared<std::string>();
+    jsonStr->reserve(queries * 36);
+    jsonStr->append("[", 1);
     for (int i = 0; i < queries; i++)
     {
         int id = rand() % 10000 + 1;
         *client << "select randomnumber from world where id=$1" << id >>
-            [callbackPtr, counter, json, id](const Result &r) mutable {
+            [callbackPtr, counter, jsonStr, id](const Result &r) mutable {
                 (*counter)--;
                 if (r.size() > 0)
                 {
-                    Json::Value j;
-                    j["id"] = id;
-                    j["randomnumber"] = r[0]["randomnumber"].as<int>();
-                    json->append(std::move(j));
+                    char json[64];
+                    auto size = sprintf(json,
+                                        "{\"id\":%d,\"randomnumber\":%s}",
+                                        id,
+                                        r[0]["randomnumber"].c_str());
+                    jsonStr->append(json, size);
                 }
                 if ((*counter) == 0)
                 {
-                    (*callbackPtr)(HttpResponse::newHttpJsonResponse(*json));
+                    jsonStr->append("]", 1);
+                    auto resp = HttpResponse::newHttpResponse();
+                    resp->setContentTypeCode(ContentType::CT_APPLICATION_JSON);
+                    resp->setBody(std::move(*jsonStr));
+                    (*callbackPtr)(resp);
+                }
+                else
+                {
+                    jsonStr->append(",");
                 }
             } >>
             [callbackPtr](const DrogonDbException &e) {

+ 7 - 5
frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrlRaw.h

@@ -1,12 +1,14 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class QueriesCtrlRaw:public drogon::HttpSimpleController<QueriesCtrlRaw>
+class QueriesCtrlRaw : public drogon::HttpSimpleController<QueriesCtrlRaw>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
+    // list path definitions here;
+    // PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
     PATH_LIST_END
 };

+ 40 - 32
frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrl.cc

@@ -4,13 +4,13 @@
 
 using namespace drogon_model::hello_world;
 
-void UpdatesCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback)
+void UpdatesCtrl::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
-    //write your application logic here
+    // write your application logic here
     static std::once_flag once;
-    std::call_once(once, []() {
-        srand(time(NULL));
-    });
+    std::call_once(once, []() { srand(time(NULL)); });
     int queries = 1;
     auto &parameter = req->getParameter("queries");
     if (!parameter.empty())
@@ -23,7 +23,9 @@ void UpdatesCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::functio
     }
     auto json = std::make_shared<Json::Value>();
     json->resize(0);
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
     auto counter = std::make_shared<int>(queries);
     auto client = app().getFastDbClient();
     drogon::orm::Mapper<World> mapper(client);
@@ -31,31 +33,37 @@ void UpdatesCtrl::asyncHandleHttpRequest(const HttpRequestPtr &req, std::functio
     for (int i = 0; i < queries; i++)
     {
         World::PrimaryKeyType id = rand() % 10000 + 1;
-        mapper.findByPrimaryKey(id,
-                                [callbackPtr, counter, json, client](World w) mutable {
-                                    w.setRandomnumber(rand() % 10000 + 1);
-                                    drogon::orm::Mapper<World> mapper(client);
-                                    mapper.update(w,
-                                                  [w, json = std::move(json), counter = std::move(counter), callbackPtr](const size_t count) {
-                                                      json->append(w.toJson());
-                                                      (*counter)--;
-                                                      if ((*counter) == 0)
-                                                      {
-                                                          (*callbackPtr)(HttpResponse::newHttpJsonResponse(*json));
-                                                      }
-                                                  },
-                                                  [callbackPtr](const DrogonDbException &e) {
-                                                      Json::Value ret;
-                                                      ret["result"] = "error!";
-                                                      auto resp = HttpResponse::newHttpJsonResponse(ret);
-                                                      (*callbackPtr)(resp);
-                                                  });
-                                },
-                                [callbackPtr](const DrogonDbException &e) {
-                                    Json::Value ret;
-                                    ret["result"] = "error!";
-                                    auto resp = HttpResponse::newHttpJsonResponse(ret);
-                                    (*callbackPtr)(resp);
-                                });
+        mapper.findByPrimaryKey(
+            id,
+            [callbackPtr, counter, json, client](World w) mutable {
+                w.setRandomnumber(rand() % 10000 + 1);
+                drogon::orm::Mapper<World> mapper(client);
+                mapper.update(
+                    w,
+                    [w,
+                     json = std::move(json),
+                     counter = std::move(counter),
+                     callbackPtr](const size_t count) {
+                        json->append(w.toJson());
+                        (*counter)--;
+                        if ((*counter) == 0)
+                        {
+                            (*callbackPtr)(
+                                HttpResponse::newHttpJsonResponse(*json));
+                        }
+                    },
+                    [callbackPtr](const DrogonDbException &e) {
+                        Json::Value ret;
+                        ret["result"] = "error!";
+                        auto resp = HttpResponse::newHttpJsonResponse(ret);
+                        (*callbackPtr)(resp);
+                    });
+            },
+            [callbackPtr](const DrogonDbException &e) {
+                Json::Value ret;
+                ret["result"] = "error!";
+                auto resp = HttpResponse::newHttpJsonResponse(ret);
+                (*callbackPtr)(resp);
+            });
     }
 }

+ 5 - 3
frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrl.h

@@ -4,9 +4,11 @@ using namespace drogon;
 class UpdatesCtrl : public drogon::HttpSimpleController<UpdatesCtrl>
 {
   public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback) override;
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
+    // list path definitions here;
+    // PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
     PATH_LIST_END
 };

+ 44 - 35
frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrlRaw.cc

@@ -1,10 +1,11 @@
 #include "UpdatesCtrlRaw.h"
 using namespace drogon::orm;
-const void update(const std::shared_ptr<std::vector<Result>> &results,
-                  const std::shared_ptr<std::function<void(const HttpResponsePtr &)>> &callbackPtr,
-                  const DbClientPtr &client)
+const void update(
+    const std::shared_ptr<std::vector<Result>> &results,
+    const std::shared_ptr<std::function<void(const HttpResponsePtr &)>>
+        &callbackPtr,
+    const DbClientPtr &client)
 {
-
     auto size = results->size();
     std::string sql;
     sql.reserve(256);
@@ -12,14 +13,17 @@ const void update(const std::shared_ptr<std::vector<Result>> &results,
     int placeholdersCounter = 1;
     for (size_t i = 0; i < size; i++)
     {
-        auto tmpStr = drogon::utils::formattedString("when $%d then $%d ", placeholdersCounter, placeholdersCounter + 1);
+        auto tmpStr = drogon::utils::formattedString("when $%d then $%d ",
+                                                     placeholdersCounter,
+                                                     placeholdersCounter + 1);
         placeholdersCounter += 2;
         sql.append(tmpStr);
     }
     sql.append("else randomnumber end where id in (");
     for (size_t i = 0; i < size; i++)
     {
-        auto tmpStr = drogon::utils::formattedString("$%d,", placeholdersCounter);
+        auto tmpStr =
+            drogon::utils::formattedString("$%d,", placeholdersCounter);
         ++placeholdersCounter;
         sql.append(tmpStr);
     }
@@ -27,42 +31,47 @@ const void update(const std::shared_ptr<std::vector<Result>> &results,
 
     auto sqlBinder = *client << std::move(sql);
 
-    auto jsonPtr = std::make_shared<Json::Value>();
-    jsonPtr->resize(0);
-    for (auto &r : *results)
+    std::string jsonStr;
+    jsonStr.reserve(size * 36);
+    jsonStr.append("[", 1);
+    for (auto const &r : *results)
     {
         auto randId = rand() % 10000 + 1;
         auto id = r[0]["id"].as<int>();
         sqlBinder << id;
         sqlBinder << randId;
-        Json::Value j;
-        j["id"] = id;
-        j["randomnumber"] = randId;
-        jsonPtr->append(std::move(j));
+        char json[64];
+        auto size =
+            sprintf(json, "{\"id\":%d,\"randomnumber\":%d}", id, randId);
+        jsonStr.append(json, size);
+        jsonStr.append(",", 1);
     }
-    for (auto &r : *results)
+    jsonStr[jsonStr.length() - 1] = ']';
+    for (auto const &r : *results)
     {
         sqlBinder << r[0]["id"].as<int>();
     }
 
-    sqlBinder >>
-        [jsonPtr = std::move(jsonPtr), callbackPtr](const Result &r) mutable {
-            (*callbackPtr)(HttpResponse::newHttpJsonResponse(*jsonPtr));
-        } >>
-        [callbackPtr](const DrogonDbException &e) {
-            Json::Value ret;
-            ret["result"] = "error!";
-            auto resp = HttpResponse::newHttpJsonResponse(ret);
-            (*callbackPtr)(resp);
-        };
+    sqlBinder >> [jsonStr = std::move(jsonStr),
+                  callbackPtr](const Result &r) mutable {
+        auto resp = HttpResponse::newHttpResponse();
+        resp->setContentTypeCode(ContentType::CT_APPLICATION_JSON);
+        resp->setBody(std::move(jsonStr));
+        (*callbackPtr)(resp);
+    } >> [callbackPtr](const DrogonDbException &e) {
+        Json::Value ret;
+        ret["result"] = "error!";
+        auto resp = HttpResponse::newHttpJsonResponse(ret);
+        (*callbackPtr)(resp);
+    };
 }
-void UpdatesCtrlRaw::asyncHandleHttpRequest(const HttpRequestPtr &req, std::function<void(const HttpResponsePtr &)> &&callback)
+void UpdatesCtrlRaw::asyncHandleHttpRequest(
+    const HttpRequestPtr &req,
+    std::function<void(const HttpResponsePtr &)> &&callback)
 {
-    //write your application logic here
+    // write your application logic here
     static std::once_flag once;
-    std::call_once(once, []() {
-        srand(time(NULL));
-    });
+    std::call_once(once, []() { srand(time(NULL)); });
     size_t queries = 1;
     auto &parameter = req->getParameter("queries");
     if (!parameter.empty())
@@ -73,18 +82,18 @@ void UpdatesCtrlRaw::asyncHandleHttpRequest(const HttpRequestPtr &req, std::func
         else if (queries < 1)
             queries = 1;
     }
-    auto json = std::make_shared<Json::Value>();
-    json->resize(0);
-    auto callbackPtr = std::shared_ptr<std::function<void(const HttpResponsePtr &)>>(new std::function<void(const HttpResponsePtr &)>(std::move(callback)));
+    auto callbackPtr =
+        std::make_shared<std::function<void(const HttpResponsePtr &)>>(
+            std::move(callback));
     auto resultSetPtr = std::make_shared<std::vector<Result>>();
     resultSetPtr->reserve(queries);
     auto client = app().getFastDbClient();
     for (size_t i = 0; i < queries; i++)
     {
         int id = rand() % 10000 + 1;
-        *client << "select * from world where id=$1"
-                << id >>
-            [callbackPtr, resultSetPtr, client, queries](const Result &r) mutable {
+        *client << "select * from world where id=$1" << id >>
+            [callbackPtr, resultSetPtr, client, queries](
+                const Result &r) mutable {
                 resultSetPtr->push_back(r);
                 if (resultSetPtr->size() == queries)
                 {

+ 7 - 5
frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrlRaw.h

@@ -1,12 +1,14 @@
 #pragma once
 #include <drogon/HttpSimpleController.h>
 using namespace drogon;
-class UpdatesCtrlRaw:public drogon::HttpSimpleController<UpdatesCtrlRaw>
+class UpdatesCtrlRaw : public drogon::HttpSimpleController<UpdatesCtrlRaw>
 {
-public:
-    virtual void asyncHandleHttpRequest(const HttpRequestPtr& req, std::function<void (const HttpResponsePtr &)> &&callback) override;
+  public:
+    virtual void asyncHandleHttpRequest(
+        const HttpRequestPtr &req,
+        std::function<void(const HttpResponsePtr &)> &&callback) override;
     PATH_LIST_BEGIN
-    //list path definitions here;
-    //PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
+    // list path definitions here;
+    // PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
     PATH_LIST_END
 };

+ 5 - 2
frameworks/C++/drogon/drogon_benchmark/views/fortune.csp

@@ -11,8 +11,11 @@ auto &rows=@@.get<std::vector<Fortune>>("rows");
 <body>
 <table>
 <tr><th>id</th><th>message</th></tr>
-<%c++for(auto &row:rows){%>
-<tr><td>{%row.getValueOfId()%}</td><td>{%HttpViewData::htmlTranslate(row.getValueOfMessage())%}</td></tr>
+<%c++for(auto const &row:rows){%>
+<tr><td>{%row.getValueOfId()%}</td><td><%c++ if(HttpViewData::needTranslation(row.getValueOfMessage()))
+                                         $$<<HttpViewData::htmlTranslate(row.getValueOfMessage());
+                                    else
+                                         $$<<row.getValueOfMessage();%></td></tr>
 <%c++}%>
 </table>
 </body>

+ 7 - 4
frameworks/C++/drogon/drogon_benchmark/views/fortune_raw.csp

@@ -1,5 +1,5 @@
 <%c++
-auto &rows=@@.get<std::vector<std::pair<int,std::string>>>("rows");
+auto &rows=@@.get<std::vector<std::pair<string_view,string_view>>>("rows");
 %>
 <!DOCTYPE html>
 <html>
@@ -7,9 +7,12 @@ auto &rows=@@.get<std::vector<std::pair<int,std::string>>>("rows");
 <body>
 <table>
 <tr><th>id</th><th>message</th></tr>
-<%c++for(auto &row:rows){%>
-<tr><td>{%row.first%}</td><td>{%HttpViewData::htmlTranslate(row.second)%}</td></tr>
+<%c++for(auto const &row:rows){%>
+<tr><td>{%row.first%}</td><td><%c++ if(HttpViewData::needTranslation(row.second))
+                                         $$<<HttpViewData::htmlTranslate(row.second);
+                                    else
+                                         $$<<row.second;%></td></tr>
 <%c++}%>
 </table>
 </body>
-</html>
+</html>