From: Remi Gacogne Date: Fri, 27 Jun 2025 10:12:29 +0000 (+0200) Subject: lmdb-safe: Improve the scalability of transaction maps X-Git-Tag: rec-5.3.0-alpha2~38^2~1 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c340aa91bf37d8105d2b2390eecbadfca88c1d27;p=thirdparty%2Fpdns.git lmdb-safe: Improve the scalability of transaction maps This commit improves the scalability of the transaction maps by moving from a `mutex` to a `shared_mutex` and making the stored value atomic. This allows accessing the maps concurrently from different threads as long as the entry for the thread exists, and we fall back to taking a full lock otherwise. Signed-off-by: Remi Gacogne --- diff --git a/ext/lmdb-safe/lmdb-safe.cc b/ext/lmdb-safe/lmdb-safe.cc index 84866cfa22..e567d0884b 100644 --- a/ext/lmdb-safe/lmdb-safe.cc +++ b/ext/lmdb-safe/lmdb-safe.cc @@ -135,37 +135,84 @@ Various other options may also need to be set before opening the handle, e.g. md void MDBEnv::incROTX() { - std::lock_guard l(d_countmutex); - ++d_ROtransactionsOut[std::this_thread::get_id()]; + auto threadId = std::this_thread::get_id(); + { + std::shared_lock lock(d_countmutex); + if (auto transactionsIt = d_ROtransactionsOut.find(threadId); transactionsIt != d_ROtransactionsOut.end()) { + ++transactionsIt->second; + return; + } + } + + { + std::unique_lock lock(d_countmutex); + auto [transactionsIt, inserted] = d_ROtransactionsOut.emplace(threadId, 1); + if (!inserted) { + ++transactionsIt->second; + } + } } void MDBEnv::decROTX() { - std::lock_guard l(d_countmutex); - --d_ROtransactionsOut[std::this_thread::get_id()]; + auto threadId = std::this_thread::get_id(); + { + std::shared_lock lock(d_countmutex); + d_ROtransactionsOut.at(threadId)--; + } } void MDBEnv::incRWTX() { - std::lock_guard l(d_countmutex); - ++d_RWtransactionsOut[std::this_thread::get_id()]; + auto threadId = std::this_thread::get_id(); + { + std::shared_lock lock(d_countmutex); + if (auto transactionsIt = d_RWtransactionsOut.find(threadId); transactionsIt != d_RWtransactionsOut.end()) { + ++transactionsIt->second; + return; + } + } + + { + std::unique_lock lock(d_countmutex); + auto [transactionsIt, inserted] = d_RWtransactionsOut.emplace(threadId, 1); + if (!inserted) { + ++transactionsIt->second; + } + } } void MDBEnv::decRWTX() { - std::lock_guard l(d_countmutex); - --d_RWtransactionsOut[std::this_thread::get_id()]; + auto threadId = std::this_thread::get_id(); + { + std::shared_lock lock(d_countmutex); + d_RWtransactionsOut.at(threadId)--; + } } int MDBEnv::getRWTX() { - std::lock_guard l(d_countmutex); - return d_RWtransactionsOut[std::this_thread::get_id()]; + auto threadId = std::this_thread::get_id(); + { + std::shared_lock lock(d_countmutex); + if (auto transactionsIt = d_RWtransactionsOut.find(threadId); transactionsIt != d_RWtransactionsOut.end()) { + return transactionsIt->second.load(); + } + } + return 0; } + int MDBEnv::getROTX() { - std::lock_guard l(d_countmutex); - return d_ROtransactionsOut[std::this_thread::get_id()]; + auto threadId = std::this_thread::get_id(); + { + std::shared_lock lock(d_countmutex); + if (auto transactionsIt = d_RWtransactionsOut.find(threadId); transactionsIt != d_RWtransactionsOut.end()) { + return transactionsIt->second.load(); + } + } + return 0; } diff --git a/ext/lmdb-safe/lmdb-safe.hh b/ext/lmdb-safe/lmdb-safe.hh index 7b775d3a76..80f4f408a4 100644 --- a/ext/lmdb-safe/lmdb-safe.hh +++ b/ext/lmdb-safe/lmdb-safe.hh @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -114,9 +115,9 @@ public: void decROTX(); private: std::mutex d_openmut; - std::mutex d_countmutex; - std::map d_RWtransactionsOut; - std::map d_ROtransactionsOut; + std::shared_mutex d_countmutex; + std::map> d_RWtransactionsOut; + std::map> d_ROtransactionsOut; }; std::shared_ptr getMDBEnv(const char* fname, int flags, int mode, uint64_t mapsizeMB);