Browse Source

Optimize some tests of drogon (#5366)

* Optimize some tests of drogon

* Modify views of fortune tests
An Tao 5 years ago
parent
commit
34f9e25c0c

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

@@ -44,7 +44,7 @@ RUN git clone https://github.com/an-tao/drogon
 
 WORKDIR $DROGON_ROOT
 
-RUN git checkout feb0b73e783190185954a3626706aeaec802bf6d
+RUN git checkout 668533fbbd20eb9c493841b0e1067097aadf0342
 RUN git submodule update --init
 RUN mkdir build
 

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

@@ -44,7 +44,7 @@ RUN git clone https://github.com/an-tao/drogon
 
 WORKDIR $DROGON_ROOT
 
-RUN git checkout feb0b73e783190185954a3626706aeaec802bf6d
+RUN git checkout 668533fbbd20eb9c493841b0e1067097aadf0342
 RUN git submodule update --init
 RUN mkdir build
 

+ 7 - 6
frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrl.cc

@@ -7,17 +7,17 @@ void FortuneCtrl::asyncHandleHttpRequest(
     const HttpRequestPtr &req,
     std::function<void(const HttpResponsePtr &)> &&callback)
 {
-    if (!*_dbClient)
+    if (!*dbClient_)
     {
-        *_dbClient = drogon::app().getFastDbClient();
+        *dbClient_ = drogon::app().getFastDbClient();
     }
-    drogon::orm::Mapper<Fortune> mapper(*_dbClient);
+    drogon::orm::Mapper<Fortune> mapper(*dbClient_);
     auto callbackPtr =
         std::make_shared<std::function<void(const HttpResponsePtr &)>>(
             std::move(callback));
 
     mapper.findAll(
-        [callbackPtr](std::vector<Fortune> rows) {
+        [callbackPtr, this](std::vector<Fortune> rows) {
             Fortune newRow;
             newRow.setId(0);
             newRow.setMessage("Additional fortune added at request time.");
@@ -34,7 +34,8 @@ void FortuneCtrl::asyncHandleHttpRequest(
                       });
             HttpViewData data;
             data.insert("rows", std::move(rows));
-            auto resp = HttpResponse::newHttpViewResponse("fortune.csp", data);
+            auto resp = HttpResponse::newHttpResponse();
+            resp->setBody(bodyTemplate_->genText(data));
             (*callbackPtr)(resp);
         },
         [callbackPtr](const DrogonDbException &err) {
@@ -42,4 +43,4 @@ void FortuneCtrl::asyncHandleHttpRequest(
             resp->setBody(std::string("error:") + err.base().what());
             (*callbackPtr)(resp);
         });
-}
+}

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

@@ -6,6 +6,10 @@ using namespace drogon;
 class FortuneCtrl : public drogon::HttpSimpleController<FortuneCtrl>
 {
   public:
+    FortuneCtrl()
+        : bodyTemplate_(DrTemplateBase::newTemplate("fortune.csp"))
+    {
+    }
     virtual void asyncHandleHttpRequest(
         const HttpRequestPtr &req,
         std::function<void(const HttpResponsePtr &)> &&callback) override;
@@ -13,5 +17,6 @@ class FortuneCtrl : public drogon::HttpSimpleController<FortuneCtrl>
     // list path definitions here;
     PATH_LIST_END
   private:
-    IOThreadStorage<orm::DbClientPtr> _dbClient;
+    IOThreadStorage<orm::DbClientPtr> dbClient_;
+    std::shared_ptr<drogon::DrTemplateBase> bodyTemplate_;
 };

+ 32 - 36
frameworks/C++/drogon/drogon_benchmark/controllers/FortuneCtrlRaw.cc

@@ -8,46 +8,42 @@ void FortuneCtrlRaw::asyncHandleHttpRequest(
     const HttpRequestPtr &req,
     std::function<void(const HttpResponsePtr &)> &&callback)
 {
-    if (!*_dbClient)
+    if (!*dbClient_)
     {
-        *_dbClient = drogon::app().getFastDbClient();
+        *dbClient_ = drogon::app().getFastDbClient();
     }
     auto callbackPtr =
         std::make_shared<std::function<void(const HttpResponsePtr &)>>(
             std::move(callback));
 
-    **_dbClient << "select * from fortune where 1=$1" << 1 >>
-        [callbackPtr](const Result &r) {
-            std::vector<Fortune> rows;
-            rows.reserve(r.size() + 1);
-            for (auto const &row : r)
-            {
-                rows.emplace_back(row[0ul].as<string_view>(),   // id
-                                  row[1ul].as<string_view>());  // message
-            }
-            Fortune newRow;
-            newRow.id_ = "0";
-            newRow.message_ = "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.message_ < f2.message_)
-                              return true;
-                          else
-                          {
-                              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);
-        };
+    **dbClient_ << "select * from fortune" >> [callbackPtr,
+                                               this](const Result &r) {
+        std::vector<Fortune> rows;
+        rows.reserve(r.size() + 1);
+        for (auto const &row : r)
+        {
+            rows.emplace_back(row[0ul].as<string_view>(),   // id
+                              row[1ul].as<string_view>());  // message
+        }
+        rows.emplace_back("0", "Additional fortune added at request time.");
+        std::sort(rows.begin(),
+                  rows.end(),
+                  [](const Fortune &f1, const Fortune &f2) -> bool {
+                      if (f1.message_ < f2.message_)
+                          return true;
+                      else
+                      {
+                          return false;
+                      }
+                  });
+        HttpViewData data;
+        data.insert("rows", std::move(rows));
+        auto resp = HttpResponse::newHttpResponse();
+        resp->setBody(bodyTemplate_->genText(data));
+        (*callbackPtr)(resp);
+    } >> [callbackPtr](const DrogonDbException &err) {
+        auto resp = HttpResponse::newHttpResponse();
+        resp->setBody(std::string("error:") + err.base().what());
+        (*callbackPtr)(resp);
+    };
 }

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

@@ -16,6 +16,10 @@ struct Fortune
 class FortuneCtrlRaw : public drogon::HttpSimpleController<FortuneCtrlRaw>
 {
   public:
+    FortuneCtrlRaw()
+        : bodyTemplate_(DrTemplateBase::newTemplate("fortune_raw.csp"))
+    {
+    }
     virtual void asyncHandleHttpRequest(
         const HttpRequestPtr &req,
         std::function<void(const HttpResponsePtr &)> &&callback) override;
@@ -23,5 +27,6 @@ class FortuneCtrlRaw : public drogon::HttpSimpleController<FortuneCtrlRaw>
     // list path definitions here;
     PATH_LIST_END
   private:
-    IOThreadStorage<orm::DbClientPtr> _dbClient;
+    IOThreadStorage<orm::DbClientPtr> dbClient_;
+    std::shared_ptr<drogon::DrTemplateBase> bodyTemplate_;
 };

+ 8 - 3
frameworks/C++/drogon/drogon_benchmark/controllers/QueriesCtrl.cc

@@ -43,14 +43,19 @@ void QueriesCtrl::asyncHandleHttpRequest(
                 (*counter)--;
                 if ((*counter) == 0)
                 {
-                    (*callbackPtr)(HttpResponse::newHttpJsonResponse(std::move(*json)));
+                    (*callbackPtr)(
+                        HttpResponse::newHttpJsonResponse(std::move(*json)));
                 }
             },
-            [callbackPtr](const DrogonDbException &e) {
+            [callbackPtr, counter](const DrogonDbException &e) {
+                if ((*counter) <= 0)
+                    return;
+                (*counter) = -1;
                 Json::Value json{};
                 json["code"] = 1;
                 json["message"] = e.base().what();
-                (*callbackPtr)(HttpResponse::newHttpJsonResponse(std::move(json)));
+                (*callbackPtr)(
+                    HttpResponse::newHttpJsonResponse(std::move(json)));
             });
     }
 }

+ 23 - 14
frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrl.cc

@@ -26,7 +26,7 @@ void UpdatesCtrl::asyncHandleHttpRequest(
     auto callbackPtr =
         std::make_shared<std::function<void(const HttpResponsePtr &)>>(
             std::move(callback));
-    auto counter = std::make_shared<int>(queries);
+    auto errFlag = std::make_shared<bool>(false);
     if (!*_dbClient)
     {
         *_dbClient = drogon::app().getFastDbClient();
@@ -38,36 +38,45 @@ void UpdatesCtrl::asyncHandleHttpRequest(
         World::PrimaryKeyType id = rand() % 10000 + 1;
         mapper.findByPrimaryKey(
             id,
-            [callbackPtr, counter, json, &client = *_dbClient](
+            [callbackPtr, errFlag, json, &client = *_dbClient, queries](
                 World w) mutable {
+                if (*errFlag)
+                    return;
                 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) {
+                    [w, json = std::move(json), errFlag, callbackPtr, queries](
+                        const size_t count) {
+                        if (*errFlag)
+                            return;
                         json->append(w.toJson());
-                        (*counter)--;
-                        if ((*counter) == 0)
+                        if (json->size() == queries)
                         {
-                            (*callbackPtr)(
-                                HttpResponse::newHttpJsonResponse(std::move(*json)));
+                            (*callbackPtr)(HttpResponse::newHttpJsonResponse(
+                                std::move(*json)));
                         }
                     },
-                    [callbackPtr](const DrogonDbException &e) {
+                    [callbackPtr, errFlag](const DrogonDbException &e) {
+                        if (*errFlag)
+                            return;
+                        *errFlag = true;
                         Json::Value json{};
                         json["code"] = 1;
                         json["message"] = e.base().what();
-                        (*callbackPtr)(HttpResponse::newHttpJsonResponse(std::move(json)));
+                        (*callbackPtr)(
+                            HttpResponse::newHttpJsonResponse(std::move(json)));
                     });
             },
-            [callbackPtr](const DrogonDbException &e) {
+            [callbackPtr, errFlag](const DrogonDbException &e) {
+                if (*errFlag)
+                    return;
+                *errFlag = true;
                 Json::Value json{};
                 json["code"] = 1;
                 json["message"] = e.base().what();
-                (*callbackPtr)(HttpResponse::newHttpJsonResponse(std::move(json)));
+                (*callbackPtr)(
+                    HttpResponse::newHttpJsonResponse(std::move(json)));
             });
     }
 }

+ 48 - 23
frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrlRaw.cc

@@ -1,21 +1,21 @@
 #include "UpdatesCtrlRaw.h"
-#include "models/World.h"
 #include <stdlib.h>
 
-using namespace drogon_model::hello_world;
 using namespace drogon::orm;
-const void update(
-    const std::shared_ptr<std::vector<World>> &results,
-    const std::shared_ptr<std::function<void(const HttpResponsePtr &)>>
-        &callbackPtr,
-    const DbClientPtr &client)
+
+const std::string &UpdatesCtrlRaw::getSQL(size_t count)
 {
-    auto size = results->size();
+    auto &sqlMap = *updateSQLs_;
+    auto iter = sqlMap.find(count);
+    if (iter != sqlMap.end())
+    {
+        return *(iter->second);
+    }
     std::string sql;
-    sql.reserve(256);
+    sql.reserve(80 + count * 25);
     sql.append("update world set randomnumber=case id ");
     int placeholdersCounter = 1;
-    for (size_t i = 0; i < size; i++)
+    for (size_t i = 0; i < count; i++)
     {
         auto tmpStr = drogon::utils::formattedString("when $%d then $%d ",
                                                      placeholdersCounter,
@@ -24,7 +24,7 @@ const void update(
         sql.append(tmpStr);
     }
     sql.append("else randomnumber end where id in (");
-    for (size_t i = 0; i < size; i++)
+    for (size_t i = 0; i < count; i++)
     {
         auto tmpStr =
             drogon::utils::formattedString("$%d,", placeholdersCounter);
@@ -32,8 +32,18 @@ const void update(
         sql.append(tmpStr);
     }
     sql[sql.length() - 1] = ')';
-
-    auto sqlBinder = *client << std::move(sql);
+    auto ret =
+        sqlMap.insert({count, std::make_unique<std::string>(std::move(sql))});
+    return *(ret.first->second);
+}
+void UpdatesCtrlRaw::update(
+    const std::shared_ptr<std::vector<World>> &results,
+    const std::shared_ptr<std::function<void(const HttpResponsePtr &)>>
+        &callbackPtr,
+    const DbClientPtr &client)
+{
+    auto const &sql = getSQL(results->size());
+    auto sqlBinder = *client << string_view(sql.data(), sql.length());
     Json::Value json;
     json.resize(0);
     for (auto const &w : *results)
@@ -51,7 +61,8 @@ const void update(
         sqlBinder << w.getValueOfId();
     }
 
-    sqlBinder >> [callbackPtr, json = std::move(json)](const Result &r) mutable {
+    sqlBinder >> [callbackPtr,
+                  json = std::move(json)](const Result &r) mutable {
         (*callbackPtr)(HttpResponse::newHttpJsonResponse(std::move(json)));
     } >> [callbackPtr](const DrogonDbException &e) {
         Json::Value json{};
@@ -68,7 +79,7 @@ void UpdatesCtrlRaw::asyncHandleHttpRequest(
     // write your application logic here
     static std::once_flag once;
     std::call_once(once, []() { srand(time(NULL)); });
-    size_t queries = 1;
+    int queries = 1;
     auto &parameter = req->getParameter("queries");
     if (!parameter.empty())
     {
@@ -83,16 +94,23 @@ void UpdatesCtrlRaw::asyncHandleHttpRequest(
             std::move(callback));
     auto resultSetPtr = std::make_shared<std::vector<World>>();
     resultSetPtr->reserve(queries);
-    if (!*_dbClient)
+    if (!*dbClient_)
     {
-        *_dbClient = drogon::app().getFastDbClient();
+        *dbClient_ = drogon::app().getFastDbClient();
     }
-    for (size_t i = 0; i < queries; i++)
+    auto errFlag = std::make_shared<bool>(false);
+    for (int i = 0; i < queries; i++)
     {
         int id = rand() % 10000 + 1;
-        **_dbClient << "select * from world where id=$1" << id >>
-            [callbackPtr, resultSetPtr, &client = *_dbClient, queries](
-                const Result &r) mutable {
+        **dbClient_ << "select * from world where id=$1" << id >>
+            [callbackPtr,
+             resultSetPtr,
+             &client = *dbClient_,
+             queries,
+             this,
+             errFlag](const Result &r) mutable {
+                if (*errFlag)
+                    return;
                 if (r.size() == 1)
                 {
                     resultSetPtr->emplace_back(World(r[0]));
@@ -103,13 +121,20 @@ void UpdatesCtrlRaw::asyncHandleHttpRequest(
                 }
                 else
                 {
+                    if (*errFlag)
+                        return;
+                    *errFlag = true;
                     Json::Value json{};
                     json["code"] = 0;
                     json["message"] = "Internal error";
-                    (*callbackPtr)(HttpResponse::newHttpJsonResponse(std::move(json)));
+                    (*callbackPtr)(
+                        HttpResponse::newHttpJsonResponse(std::move(json)));
                 }
             } >>
-            [callbackPtr](const DrogonDbException &e) {
+            [callbackPtr, errFlag](const DrogonDbException &e) {
+                if (*errFlag)
+                    return;
+                *errFlag = true;
                 Json::Value json{};
                 json["code"] = 1;
                 json["message"] = e.base().what();

+ 14 - 1
frameworks/C++/drogon/drogon_benchmark/controllers/UpdatesCtrlRaw.h

@@ -1,8 +1,14 @@
 #pragma once
+#include "models/World.h"
 #include <drogon/HttpSimpleController.h>
 #include <drogon/IOThreadStorage.h>
+#include <map>
+#include <string>
+#include <memory>
 
 using namespace drogon;
+using namespace drogon_model::hello_world;
+
 class UpdatesCtrlRaw : public drogon::HttpSimpleController<UpdatesCtrlRaw>
 {
   public:
@@ -14,5 +20,12 @@ class UpdatesCtrlRaw : public drogon::HttpSimpleController<UpdatesCtrlRaw>
     // PATH_ADD("/path","filter1","filter2",HttpMethod1,HttpMethod2...);
     PATH_LIST_END
   private:
-    IOThreadStorage<orm::DbClientPtr> _dbClient;
+    IOThreadStorage<orm::DbClientPtr> dbClient_;
+    IOThreadStorage<std::map<size_t, std::unique_ptr<std::string>>> updateSQLs_;
+    const std::string &getSQL(size_t count);
+    void update(
+        const std::shared_ptr<std::vector<World>> &results,
+        const std::shared_ptr<std::function<void(const HttpResponsePtr &)>>
+            &callbackPtr,
+        const DbClientPtr &client);
 };

+ 2 - 1
frameworks/C++/drogon/drogon_benchmark/plugins/SyncPlugin.cc

@@ -25,7 +25,8 @@ void SyncPlugin::initAndStart(const Json::Value &config)
                     {
                         Json::Value ret;
                         ret["message"] = "Hello, World!";
-                        return HttpResponse::newHttpJsonResponse(ret);
+                        return HttpResponse::newHttpJsonResponse(
+                            std::move(ret));
                     }
                     break;
                 case 10: