Browse Source

[C++] [userver] bump userver commit and tweak PG pools once more (#8233)

* more granular concurrency limits for DB handlers

* bump userver commit

* increase coroutine limits
itrofimow 2 years ago
parent
commit
dde12fce40

+ 1 - 1
frameworks/C++/userver/userver-bare.dockerfile

@@ -2,7 +2,7 @@ FROM ghcr.io/userver-framework/ubuntu-userver-build-base:v1 AS builder
 
 WORKDIR /src
 RUN git clone https://github.com/userver-framework/userver.git && \
-    cd userver && git checkout 040b0bd001a078ee023aabe987e5ec7cc8ed5b6c
+    cd userver && git checkout 3a8ea5c0e6e1200a1ec5e8d5c87dfba3987cdd98
 COPY userver_benchmark/ ./
 RUN mkdir build && cd build && \
     cmake -DUSERVER_IS_THE_ROOT_PROJECT=0 -DUSERVER_FEATURE_CRYPTOPP_BLAKE2=0 \

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

@@ -2,7 +2,7 @@ FROM ghcr.io/userver-framework/ubuntu-userver-build-base:v1 AS builder
 
 WORKDIR /src
 RUN git clone https://github.com/userver-framework/userver.git && \
-    cd userver && git checkout 040b0bd001a078ee023aabe987e5ec7cc8ed5b6c
+    cd userver && git checkout 3a8ea5c0e6e1200a1ec5e8d5c87dfba3987cdd98
 COPY userver_benchmark/ ./
 RUN mkdir build && cd build && \
     cmake -DUSERVER_IS_THE_ROOT_PROJECT=0 -DUSERVER_FEATURE_CRYPTOPP_BLAKE2=0 \

+ 7 - 0
frameworks/C++/userver/userver_benchmark/common/db_helpers.cpp

@@ -63,4 +63,11 @@ int ParseParamFromQuery(std::string_view url, std::string_view name) {
   return ParseFromQueryVal(url.substr(pos, len));
 }
 
+DatabasePoolSemaphore::DatabasePoolSemaphore(std::size_t initial_count)
+    : semaphore_{initial_count} {}
+
+userver::engine::SemaphoreLock DatabasePoolSemaphore::Acquire() const {
+  return userver::engine::SemaphoreLock{semaphore_};
+}
+
 }  // namespace userver_techempower::db_helpers

+ 11 - 0
frameworks/C++/userver/userver_benchmark/common/db_helpers.hpp

@@ -1,5 +1,6 @@
 #pragma once
 
+#include <userver/engine/semaphore.hpp>
 #include <userver/formats/json/value.hpp>
 #include <userver/server/http/http_request.hpp>
 #include <userver/storages/postgres/cluster_types.hpp>
@@ -31,4 +32,14 @@ int ParseParamFromQuery(const userver::server::http::HttpRequest& request,
 
 int ParseParamFromQuery(std::string_view url, std::string_view name);
 
+class DatabasePoolSemaphore final {
+ public:
+  explicit DatabasePoolSemaphore(std::size_t initial_count);
+
+  userver::engine::SemaphoreLock Acquire() const;
+
+ private:
+  mutable userver::engine::Semaphore semaphore_;
+};
+
 }  // namespace userver_techempower::db_helpers

+ 10 - 7
frameworks/C++/userver/userver_benchmark/controllers/fortunes/handler.cpp

@@ -2,8 +2,6 @@
 
 #include <vector>
 
-#include "../../common/db_helpers.hpp"
-
 #include <userver/components/component_context.hpp>
 #include <userver/storages/postgres/postgres.hpp>
 
@@ -124,6 +122,8 @@ std::string FormatFortunes(const std::vector<Fortune>& fortunes) {
   return result;
 }
 
+constexpr std::size_t kBestConcurrencyWildGuess = 256;
+
 }  // namespace
 
 Handler::Handler(const userver::components::ComponentConfig& config,
@@ -133,7 +133,8 @@ Handler::Handler(const userver::components::ComponentConfig& config,
               .FindComponent<userver::components::Postgres>(
                   db_helpers::kDbComponentName)
               .GetCluster()},
-      select_all_fortunes_query_{"SELECT id, message FROM Fortune"} {}
+      select_all_fortunes_query_{"SELECT id, message FROM Fortune"},
+      semaphore_{kBestConcurrencyWildGuess} {}
 
 std::string Handler::HandleRequestThrow(
     const userver::server::http::HttpRequest& request,
@@ -143,10 +144,12 @@ std::string Handler::HandleRequestThrow(
 }
 
 std::string Handler::GetResponse() const {
-  auto fortunes =
-      pg_->Execute(db_helpers::kClusterHostType, select_all_fortunes_query_)
-          .AsContainer<std::vector<Fortune>>(
-              userver::storages::postgres::kRowTag);
+  auto fortunes = [this] {
+    const auto lock = semaphore_.Acquire();
+    return pg_->Execute(db_helpers::kClusterHostType, select_all_fortunes_query_)
+        .AsContainer<std::vector<Fortune>>(
+            userver::storages::postgres::kRowTag);
+  }();
 
   fortunes.push_back({0, "Additional fortune added at request time."});
 

+ 4 - 0
frameworks/C++/userver/userver_benchmark/controllers/fortunes/handler.hpp

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "../../common/db_helpers.hpp"
+
 #include <userver/server/handlers/http_handler_base.hpp>
 
 #include <userver/storages/postgres/postgres_fwd.hpp>
@@ -23,6 +25,8 @@ class Handler final : public userver::server::handlers::HttpHandlerBase {
  private:
   const userver::storages::postgres::ClusterPtr pg_;
   const userver::storages::postgres::Query select_all_fortunes_query_;
+
+  db_helpers::DatabasePoolSemaphore semaphore_;
 };
 
 }  // namespace userver_techempower::fortunes

+ 22 - 14
frameworks/C++/userver/userver_benchmark/controllers/multiple_queries/handler.cpp

@@ -1,7 +1,5 @@
 #include "handler.hpp"
 
-#include "../../common/db_helpers.hpp"
-
 #include <userver/components/component_context.hpp>
 #include <userver/formats/serialize/common_containers.hpp>
 #include <userver/storages/postgres/postgres.hpp>
@@ -10,6 +8,12 @@
 
 namespace userver_techempower::multiple_queries {
 
+namespace {
+
+constexpr std::size_t kBestConcurrencyWildGuess = 256;
+
+}
+
 Handler::Handler(const userver::components::ComponentConfig& config,
                  const userver::components::ComponentContext& context)
     : userver::server::handlers::HttpHandlerJsonBase{config, context},
@@ -17,7 +21,8 @@ Handler::Handler(const userver::components::ComponentConfig& config,
               .FindComponent<userver::components::Postgres>(
                   db_helpers::kDbComponentName)
               .GetCluster()},
-      query_arg_name_{"queries"} {}
+      query_arg_name_{"queries"},
+      semaphore_{kBestConcurrencyWildGuess} {}
 
 userver::formats::json::Value Handler::HandleRequestJsonThrow(
     const userver::server::http::HttpRequest& request,
@@ -40,18 +45,21 @@ userver::formats::json::Value Handler::GetResponse(int queries) const {
   // faster due to the pool semaphore contention reduction - now we have a
   // connection for ourselves until we are done with it, otherwise we would
   // likely wait on the semaphore with every new query.
-  auto transaction = pg_->Begin(
-      db_helpers::kClusterHostType,
-      userver::storages::postgres::TransactionOptions{
-          userver::storages::postgres::TransactionOptions::Mode::kReadOnly});
-  for (auto& value : result) {
-    value.random_number =
-        transaction.Execute(db_helpers::kSelectRowQuery, value.id)
-            .AsSingleRow<db_helpers::WorldTableRow>(
-                userver::storages::postgres::kRowTag)
-            .random_number;
+  {
+    const auto lock = semaphore_.Acquire();
+    auto transaction = pg_->Begin(
+        db_helpers::kClusterHostType,
+        userver::storages::postgres::TransactionOptions{
+            userver::storages::postgres::TransactionOptions::Mode::kReadOnly});
+    for (auto& value : result) {
+      value.random_number =
+          transaction.Execute(db_helpers::kSelectRowQuery, value.id)
+              .AsSingleRow<db_helpers::WorldTableRow>(
+                  userver::storages::postgres::kRowTag)
+              .random_number;
+    }
+    transaction.Commit();
   }
-  transaction.Commit();
 
   return userver::formats::json::ValueBuilder{result}.ExtractValue();
 }

+ 4 - 0
frameworks/C++/userver/userver_benchmark/controllers/multiple_queries/handler.hpp

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "../../common/db_helpers.hpp"
+
 #include <userver/server/handlers/http_handler_json_base.hpp>
 #include <userver/storages/postgres/postgres_fwd.hpp>
 
@@ -23,6 +25,8 @@ class Handler final : public userver::server::handlers::HttpHandlerJsonBase {
   const userver::storages::postgres::ClusterPtr pg_;
 
   const std::string query_arg_name_;
+
+  db_helpers::DatabasePoolSemaphore semaphore_;
 };
 
 }  // namespace userver_techempower::multiple_queries

+ 16 - 8
frameworks/C++/userver/userver_benchmark/controllers/single_query/handler.cpp

@@ -1,19 +1,24 @@
 #include "handler.hpp"
 
-#include "../../common/db_helpers.hpp"
-
 #include <userver/components/component_context.hpp>
 #include <userver/storages/postgres/postgres.hpp>
 
 namespace userver_techempower::single_query {
 
+namespace {
+
+constexpr std::size_t kBestConcurrencyWildGuess = 256;
+
+}
+
 Handler::Handler(const userver::components::ComponentConfig& config,
                  const userver::components::ComponentContext& context)
     : userver::server::handlers::HttpHandlerJsonBase{config, context},
       pg_{context
               .FindComponent<userver::components::Postgres>(
                   db_helpers::kDbComponentName)
-              .GetCluster()} {}
+              .GetCluster()},
+      semaphore_{kBestConcurrencyWildGuess} {}
 
 userver::formats::json::Value Handler::HandleRequestJsonThrow(
     const userver::server::http::HttpRequest&,
@@ -23,11 +28,14 @@ userver::formats::json::Value Handler::HandleRequestJsonThrow(
 }
 
 userver::formats::json::Value Handler::GetResponse() const {
-  const auto row =
-      pg_->Execute(db_helpers::kClusterHostType, db_helpers::kSelectRowQuery,
-                   db_helpers::GenerateRandomId())
-          .AsSingleRow<db_helpers::WorldTableRow>(
-              userver::storages::postgres::kRowTag);
+  const auto row = [this] {
+    const auto lock = semaphore_.Acquire();
+    return pg_
+        ->Execute(db_helpers::kClusterHostType, db_helpers::kSelectRowQuery,
+                  db_helpers::GenerateRandomId())
+        .AsSingleRow<db_helpers::WorldTableRow>(
+            userver::storages::postgres::kRowTag);
+  }();
 
   return db_helpers::Serialize(row, {});
 }

+ 4 - 0
frameworks/C++/userver/userver_benchmark/controllers/single_query/handler.hpp

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "../../common/db_helpers.hpp"
+
 #include <userver/server/handlers/http_handler_json_base.hpp>
 
 #include <userver/storages/postgres/postgres_fwd.hpp>
@@ -22,6 +24,8 @@ class Handler final : public userver::server::handlers::HttpHandlerJsonBase {
 
  private:
   const userver::storages::postgres::ClusterPtr pg_;
+
+  db_helpers::DatabasePoolSemaphore semaphore_;
 };
 
 }  // namespace userver_techempower::single_query

+ 5 - 3
frameworks/C++/userver/userver_benchmark/controllers/updates/handler.cpp

@@ -1,7 +1,5 @@
 #include "handler.hpp"
 
-#include "../../common/db_helpers.hpp"
-
 #include <userver/components/component_context.hpp>
 #include <userver/formats/serialize/common_containers.hpp>
 #include <userver/storages/postgres/postgres.hpp>
@@ -22,6 +20,8 @@ FROM ( SELECT
 WHERE w.id = new_numbers.id
 )"};
 
+constexpr std::size_t kBestConcurrencyWildGuess = 128;
+
 }
 
 Handler::Handler(const userver::components::ComponentConfig& config,
@@ -30,7 +30,8 @@ Handler::Handler(const userver::components::ComponentConfig& config,
       pg_{context.FindComponent<userver::components::Postgres>("hello-world-db")
               .GetCluster()},
       query_arg_name_{"queries"},
-      update_query_{kUpdateQueryStr} {}
+      update_query_{kUpdateQueryStr},
+      semaphore_{kBestConcurrencyWildGuess} {}
 
 userver::formats::json::Value Handler::HandleRequestJsonThrow(
     const userver::server::http::HttpRequest& request,
@@ -56,6 +57,7 @@ userver::formats::json::Value Handler::GetResponse(int queries) const {
   // faster due to the pool semaphore contention reduction - now we have a
   // connection for ourselves until we are done with it, otherwise we would
   // likely wait on the semaphore with every new query.
+  const auto lock = semaphore_.Acquire();
   auto transaction = pg_->Begin(db_helpers::kClusterHostType, {});
   for (auto& value : values) {
     value.random_number =

+ 4 - 0
frameworks/C++/userver/userver_benchmark/controllers/updates/handler.hpp

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "../../common/db_helpers.hpp"
+
 #include <userver/server/handlers/http_handler_json_base.hpp>
 #include <userver/storages/postgres/postgres_fwd.hpp>
 #include <userver/storages/postgres/query.hpp>
@@ -25,6 +27,8 @@ class Handler final : public userver::server::handlers::HttpHandlerJsonBase {
 
   const std::string query_arg_name_;
   const userver::storages::postgres::Query update_query_;
+
+  db_helpers::DatabasePoolSemaphore semaphore_;
 };
 
 }  // namespace userver_techempower::updates

+ 4 - 2
frameworks/C++/userver/userver_configs/dynamic_config_fallback.json

@@ -1,6 +1,8 @@
 {
   "USERVER_CACHES": {},
   "USERVER_CANCEL_HANDLE_REQUEST_BY_DEADLINE": false,
+  "POSTGRES_DEADLINE_PROPAGATION_ENABLED": false,
+  "POSTGRES_CONNECTION_PIPELINE_MODE_ENABLED": false,
   "USERVER_CHECK_AUTH_IN_HANDLERS": false,
   "USERVER_DUMPS": {},
   "USERVER_HTTP_PROXY": "",
@@ -32,8 +34,8 @@
       "default-task-processor": {
         "wait_queue_overload": {
           "action": "ignore",
-          "length_limit": 16385,
-          "time_limit_us": 30000
+          "length_limit": 300000,
+          "time_limit_us": 10000000
         }
       }
     }

+ 5 - 5
frameworks/C++/userver/userver_configs/static_config.yaml

@@ -3,9 +3,9 @@ components_manager:
     event_thread_pool:
         threads: 3
     coro_pool:
-        initial_size: 10000             # Preallocate 10000 coroutines at startup.
-        max_size: 65536                 # Do not keep more than 65536 preallocated coroutines.
-        stack_size: 66560               # 64Kb for coroutine stack
+        initial_size: 10000              # Preallocate 10000 coroutines at startup.
+        max_size: 300000                 # Do not keep more than 300000 preallocated coroutines.
+        stack_size: 66560                # 64Kb for coroutine stack
 
     task_processors:                    # Task processor is an executor for coroutine tasks
 
@@ -75,8 +75,8 @@ components_manager:
         hello-world-db:
             dbalias: hello_world
             blocking_task_processor: fs-task-processor
-            min_pool_size: 75
-            max_pool_size: 125
+            min_pool_size: 80
+            max_pool_size: 260
             max_queue_size: 512
             connecting_limit: 15