1
0
mirror of https://github.com/MariaDB/server.git synced 2026-10-23 18:49:29 +03:00

MDEV-37187 hashicorp plugin: avoid expensive clock() in hot path

The plugin used clock() only to timestamp cache entries and measure
elapsed time against millisecond timeouts. As shown in MDEV-12345,
clock() is prohibitively expensive, and we do not need per-thread or
per-process CPU time here, only time differences.

Replace clock()/clock_t with the monotonic std::chrono::steady_clock.
Timeouts are kept as std::chrono::milliseconds
This commit is contained in:
Vladislav Vaintroub
2026-06-29 16:47:59 +02:00
parent c61c995259
commit 0579ceb68d

View File

@@ -27,18 +27,32 @@
#include <algorithm>
#include <unordered_map>
#include <mutex>
#include <chrono>
#define HASHICORP_DEBUG_LOGGING 0
#define PLUGIN_ERROR_HEADER "hashicorp: "
typedef std::chrono::steady_clock::time_point time_point;
static inline time_point now ()
{
return std::chrono::steady_clock::now();
}
static inline std::chrono::milliseconds elapsed_ms (time_point from,
time_point to)
{
return std::chrono::duration_cast<std::chrono::milliseconds>(to - from);
}
/* Key version information structure: */
typedef struct VER_INFO
{
unsigned int key_version;
clock_t timestamp;
VER_INFO() : key_version(0), timestamp(0) {};
VER_INFO(unsigned int key_version_, clock_t timestamp_) :
time_point timestamp;
VER_INFO() : key_version(0), timestamp() {};
VER_INFO(unsigned int key_version_, time_point timestamp_) :
key_version(key_version_), timestamp(timestamp_) {};
} VER_INFO;
@@ -47,13 +61,13 @@ typedef struct KEY_INFO
{
unsigned int key_id;
unsigned int key_version;
clock_t timestamp;
time_point timestamp;
unsigned int length;
unsigned char data [MY_AES_MAX_KEY_LENGTH];
KEY_INFO() : key_id(0), key_version(0), timestamp(0), length(0) {};
KEY_INFO() : key_id(0), key_version(0), timestamp(), length(0) {};
KEY_INFO(unsigned int key_id_,
unsigned int key_version_,
clock_t timestamp_,
time_point timestamp_,
unsigned int length_) :
key_id(key_id_), key_version(key_version_),
timestamp(timestamp_), length(length_) {};
@@ -154,19 +168,8 @@ private:
static HCData data;
static clock_t cache_max_time;
static clock_t cache_max_ver_time;
/*
Convert milliseconds to timer ticks with rounding
to nearest integer:
*/
static clock_t ms_to_ticks (long long ms)
{
long long ticks_1000 = ms * (long long) CLOCKS_PER_SEC;
clock_t ticks = (clock_t) (ticks_1000 / 1000);
return ticks + ((clock_t) (ticks_1000 % 1000) >= 500);
}
static std::chrono::milliseconds cache_max_time;
static std::chrono::milliseconds cache_max_ver_time;
void HCData::cache_add (const KEY_INFO& info, bool update_version)
{
@@ -183,10 +186,9 @@ void HCData::cache_add (const KEY_INFO& info, bool update_version)
#if HASHICORP_DEBUG_LOGGING
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"cache_add: key_id = %u, key_version = %u, "
"timestamp = %u, update_version = %u, new version = %u",
"update_version = %u, new version = %u",
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, key_version,
ver_info.timestamp, (int) update_version,
ver_info.key_version);
(int) update_version, ver_info.key_version);
#endif
mtx.unlock();
}
@@ -197,11 +199,11 @@ unsigned int
bool with_timeouts)
{
unsigned int version = key_version;
clock_t current_time = clock();
time_point current_time = now();
mtx.lock();
if (key_version == ENCRYPTION_KEY_VERSION_INVALID)
{
clock_t timestamp;
time_point timestamp;
VER_MAP::const_iterator ver_iter = latest_version_cache.find(key_id);
if (ver_iter != latest_version_cache.end())
{
@@ -216,13 +218,12 @@ unsigned int
#if HASHICORP_DEBUG_LOGGING
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"cache_get: key_id = %u, key_version = %u, "
"last version = %u, version timestamp = %u, "
"current time = %u, diff = %u",
"last version = %u, diff (ms) = %lld",
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, key_version,
version, timestamp, current_time,
current_time - timestamp);
version,
(long long) elapsed_ms(timestamp, current_time).count());
#endif
if (with_timeouts && current_time - timestamp > cache_max_ver_time)
if (with_timeouts && elapsed_ms(timestamp, current_time) > cache_max_ver_time)
{
mtx.unlock();
return ENCRYPTION_KEY_VERSION_INVALID;
@@ -244,14 +245,13 @@ unsigned int
#if HASHICORP_DEBUG_LOGGING
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"cache_get: key_id = %u, key_version = %u, "
"effective version = %u, key data timestamp = %u, "
"current time = %u, diff = %u",
"effective version = %u, diff (ms) = %lld",
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, key_version,
version, info.timestamp, current_time,
current_time - info.timestamp);
version,
(long long) elapsed_ms(info.timestamp, current_time).count());
#endif
unsigned int length= info.length;
if (with_timeouts && current_time - info.timestamp > cache_max_time)
if (with_timeouts && elapsed_ms(info.timestamp, current_time) > cache_max_time)
{
return ENCRYPTION_KEY_VERSION_INVALID;
}
@@ -296,7 +296,7 @@ unsigned int HCData::cache_get_version (unsigned int key_id)
unsigned int HCData::cache_check_version (unsigned int key_id)
{
unsigned int version;
clock_t timestamp;
time_point timestamp;
mtx.lock();
VER_MAP::const_iterator ver_iter = latest_version_cache.find(key_id);
if (ver_iter != latest_version_cache.end())
@@ -316,17 +316,15 @@ unsigned int HCData::cache_check_version (unsigned int key_id)
return ENCRYPTION_KEY_VERSION_INVALID;
}
mtx.unlock();
clock_t current_time = clock();
time_point current_time = now();
#if HASHICORP_DEBUG_LOGGING
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
"cache_check_version: key_id = %u, "
"last version = %u, version timestamp = %u, "
"current time = %u, diff = %u",
"last version = %u, diff (ms) = %lld",
ME_ERROR_LOG_ONLY | ME_NOTE, key_id, version,
version, timestamp, current_time,
current_time - timestamp);
(long long) elapsed_ms(timestamp, current_time).count());
#endif
if (current_time - timestamp <= cache_max_ver_time)
if (elapsed_ms(timestamp, current_time) <= cache_max_ver_time)
{
return version;
}
@@ -395,7 +393,7 @@ static void cache_timeout_update (MYSQL_THD thd,
{
long long timeout = * (long long *) save;
* (long long *) var_ptr = timeout;
cache_max_time = ms_to_ticks(timeout);
cache_max_time = std::chrono::milliseconds(timeout);
}
static MYSQL_SYSVAR_LONGLONG(cache_timeout, cache_timeout,
@@ -411,7 +409,7 @@ static void
{
long timeout = * (long *) save;
* (long *) var_ptr = timeout;
cache_max_ver_time = ms_to_ticks(timeout);
cache_max_ver_time = std::chrono::milliseconds(timeout);
}
static MYSQL_SYSVAR_LONG(cache_version_timeout, cache_version_timeout,
@@ -784,7 +782,7 @@ unsigned int HCData::get_latest_version (unsigned int key_id)
return ENCRYPTION_KEY_VERSION_INVALID;
}
unsigned int length = (unsigned int) key_len >> 1;
KEY_INFO info(key_id, version, clock(), length);
KEY_INFO info(key_id, version, now(), length);
if (length > sizeof(info.data))
{
my_printf_error(ER_UNKNOWN_ERROR, PLUGIN_ERROR_HEADER
@@ -910,7 +908,7 @@ unsigned int HCData::get_key_from_vault (unsigned int key_id,
}
if (caching_enabled)
{
KEY_INFO info(key_id, (unsigned int) version, clock(), length);
KEY_INFO info(key_id, (unsigned int) version, now(), length);
memcpy(info.data, dstbuf, length);
cache_add(info, key_version == ENCRYPTION_KEY_VERSION_INVALID);
}
@@ -1152,8 +1150,8 @@ No_Secret:
}
memcpy(vault_url_data, vault_url, vault_url_len);
memcpy(vault_url_data + vault_url_len, "/data/", 7);
cache_max_time = ms_to_ticks(cache_timeout);
cache_max_ver_time = ms_to_ticks(cache_version_timeout);
cache_max_time = std::chrono::milliseconds(cache_timeout);
cache_max_ver_time = std::chrono::milliseconds(cache_version_timeout);
/* Initialize curl: */
CURLcode curl_res = curl_global_init(CURL_GLOBAL_ALL);
if (curl_res != CURLE_OK)