From 28cbaef11033f98da1a654e94fe767efa199bd7c Mon Sep 17 00:00:00 2001 From: Vlad Zolotarov Date: Tue, 9 Dec 2025 19:07:54 -0500 Subject: [PATCH] service/client_state and alternator/server: use cached values for driver_name and driver_version fields Optimize memory usage changing types of driver_name and driver_version be a reference to a cached value instead of an sstring. These fields very often have the same value among different connections hence it makes sense to cache these values and use references to them instead of duplicating such strings in each connection state. Signed-off-by: Vlad Zolotarov --- alternator/server.cc | 6 +++++- alternator/server.hh | 3 ++- client_data.hh | 4 ++-- db/virtual_tables.cc | 4 ++-- service/client_state.hh | 23 +++++++++++++++-------- transport/server.cc | 4 ++-- 6 files changed, 28 insertions(+), 16 deletions(-) diff --git a/alternator/server.cc b/alternator/server.cc index dfb00b50e8..05f1c70fba 100644 --- a/alternator/server.cc +++ b/alternator/server.cc @@ -708,8 +708,12 @@ future server::handle_api_request(std::unique_ptr // As long as the system_clients_entry object is alive, this request will // be visible in the "system.clients" virtual table. When requested, this // entry will be formatted by server::ongoing_request::make_client_data(). + auto user_agent_header = co_await _connection_options_keys_and_values.get_or_load(req->get_header("User-Agent"), [] (const client_options_cache_key_type&) { + return make_ready_future(options_cache_value_type{}); + }); + auto system_clients_entry = _ongoing_requests.emplace( - req->get_client_address(), req->get_header("User-Agent"), + req->get_client_address(), std::move(user_agent_header), username, current_scheduling_group(), req->get_protocol_name() == "https"); diff --git a/alternator/server.hh b/alternator/server.hh index 15ff86e933..a98482985b 100644 --- a/alternator/server.hh +++ b/alternator/server.hh @@ -55,6 +55,7 @@ class server : public peering_sharded_service { // though it isn't really relevant for Alternator which defines its own // timeouts separately. We can create this object only once. updateable_timeout_config _timeout_config; + client_options_cache_type _connection_options_keys_and_values; alternator_callbacks_map _callbacks; @@ -88,7 +89,7 @@ class server : public peering_sharded_service { // is called when reading the "system.clients" virtual table. struct ongoing_request { socket_address _client_address; - sstring _user_agent; + client_options_cache_entry_type _user_agent; sstring _username; scheduling_group _scheduling_group; bool _is_https; diff --git a/client_data.hh b/client_data.hh index 73a0153cdf..cc13ddf5c8 100644 --- a/client_data.hh +++ b/client_data.hh @@ -53,8 +53,8 @@ struct client_data { client_connection_stage connection_stage = client_connection_stage::established; int32_t shard_id; /// ID of server-side shard which is processing the connection. - std::optional driver_name; - std::optional driver_version; + std::optional driver_name; + std::optional driver_version; std::optional hostname; std::optional protocol_version; std::optional ssl_cipher_suite; diff --git a/db/virtual_tables.cc b/db/virtual_tables.cc index d5d07bbf4a..6e9a592db1 100644 --- a/db/virtual_tables.cc +++ b/db/virtual_tables.cc @@ -835,10 +835,10 @@ class clients_table : public streaming_virtual_table { set_cell(cr.cells(), "shard_id", cd->shard_id); set_cell(cr.cells(), "connection_stage", cd->stage_str()); if (cd->driver_name) { - set_cell(cr.cells(), "driver_name", *cd->driver_name); + set_cell(cr.cells(), "driver_name", cd->driver_name->key()); } if (cd->driver_version) { - set_cell(cr.cells(), "driver_version", *cd->driver_version); + set_cell(cr.cells(), "driver_version", cd->driver_version->key()); } if (cd->hostname) { set_cell(cr.cells(), "hostname", *cd->hostname); diff --git a/service/client_state.hh b/service/client_state.hh index 95415779ab..a5c1ab9f0b 100644 --- a/service/client_state.hh +++ b/service/client_state.hh @@ -103,8 +103,8 @@ private: private volatile String keyspace; #endif std::optional _user; - std::optional _driver_name, _driver_version; - std::list _client_options; + std::optional _driver_name, _driver_version; + std::list _client_options; auth_state _auth_state = auth_state::UNINITIALIZED; bool _control_connection = false; @@ -153,11 +153,13 @@ public: return _control_connection = true; } - std::optional get_driver_name() const { + std::optional get_driver_name() const { return _driver_name; } - void set_driver_name(sstring driver_name) { - _driver_name = std::move(driver_name); + future<> set_driver_name(client_options_cache_type& keys_and_values_cache, const sstring& driver_name) { + _driver_name = co_await keys_and_values_cache.get_or_load(driver_name, [] (const client_options_cache_key_type&) { + return make_ready_future(options_cache_value_type{}); + }); } const auto& get_client_options() const { @@ -168,11 +170,16 @@ public: client_options_cache_type& keys_and_values_cache, const std::unordered_map& client_options); - std::optional get_driver_version() const { + std::optional get_driver_version() const { return _driver_version; } - void set_driver_version(sstring driver_version) { - _driver_version = std::move(driver_version); + future<> set_driver_version( + client_options_cache_type& keys_and_values_cache, + const sstring& driver_version) + { + _driver_version = co_await keys_and_values_cache.get_or_load(driver_version, [] (const client_options_cache_key_type&) { + return make_ready_future(options_cache_value_type{}); + }); } client_state(external_tag, diff --git a/transport/server.cc b/transport/server.cc index abef5794be..89f70e6702 100644 --- a/transport/server.cc +++ b/transport/server.cc @@ -959,10 +959,10 @@ future> cql_server::connection::process_st } if (auto driver_ver_opt = options.find("DRIVER_VERSION"); driver_ver_opt != options.end()) { - _client_state.set_driver_version(driver_ver_opt->second); + co_await _client_state.set_driver_version(_server._connection_options_keys_and_values, driver_ver_opt->second); } if (auto driver_name_opt = options.find("DRIVER_NAME"); driver_name_opt != options.end()) { - _client_state.set_driver_name(driver_name_opt->second); + co_await _client_state.set_driver_name(_server._connection_options_keys_and_values, driver_name_opt->second); } // Store all received client options for later exposure in the system.clients 'client_options' column