Use unordered_lru_cache in CRecoveredSigsDb

This commit is contained in:
Alexander Block 2019-03-11 07:31:08 +01:00
parent 9e4aa1f98c
commit 293c9ad6a1
2 changed files with 22 additions and 62 deletions

View File

@ -37,66 +37,57 @@ bool CRecoveredSigsDb::HasRecoveredSig(Consensus::LLMQType llmqType, const uint2
bool CRecoveredSigsDb::HasRecoveredSigForId(Consensus::LLMQType llmqType, const uint256& id) bool CRecoveredSigsDb::HasRecoveredSigForId(Consensus::LLMQType llmqType, const uint256& id)
{ {
int64_t t = GetTimeMillis();
auto cacheKey = std::make_pair(llmqType, id); auto cacheKey = std::make_pair(llmqType, id);
bool ret;
{ {
LOCK(cs); LOCK(cs);
auto it = hasSigForIdCache.find(cacheKey); if (hasSigForIdCache.get(cacheKey, ret)) {
if (it != hasSigForIdCache.end()) { return ret;
it->second.second = t;
return it->second.first;
} }
} }
auto k = std::make_tuple(std::string("rs_r"), (uint8_t)llmqType, id); auto k = std::make_tuple(std::string("rs_r"), (uint8_t)llmqType, id);
bool ret = db.Exists(k); ret = db.Exists(k);
LOCK(cs); LOCK(cs);
hasSigForIdCache.emplace(cacheKey, std::make_pair(ret, t)); hasSigForIdCache.insert(cacheKey, ret);
return ret; return ret;
} }
bool CRecoveredSigsDb::HasRecoveredSigForSession(const uint256& signHash) bool CRecoveredSigsDb::HasRecoveredSigForSession(const uint256& signHash)
{ {
int64_t t = GetTimeMillis(); bool ret;
{ {
LOCK(cs); LOCK(cs);
auto it = hasSigForSessionCache.find(signHash); if (hasSigForSessionCache.get(signHash, ret)) {
if (it != hasSigForSessionCache.end()) { return ret;
it->second.second = t;
return it->second.first;
} }
} }
auto k = std::make_tuple(std::string("rs_s"), signHash); auto k = std::make_tuple(std::string("rs_s"), signHash);
bool ret = db.Exists(k); ret = db.Exists(k);
LOCK(cs); LOCK(cs);
hasSigForSessionCache.emplace(signHash, std::make_pair(ret, t)); hasSigForSessionCache.insert(signHash, ret);
return ret; return ret;
} }
bool CRecoveredSigsDb::HasRecoveredSigForHash(const uint256& hash) bool CRecoveredSigsDb::HasRecoveredSigForHash(const uint256& hash)
{ {
int64_t t = GetTimeMillis(); bool ret;
{ {
LOCK(cs); LOCK(cs);
auto it = hasSigForHashCache.find(hash); if (hasSigForHashCache.get(hash, ret)) {
if (it != hasSigForHashCache.end()) { return ret;
it->second.second = t;
return it->second.first;
} }
} }
auto k = std::make_tuple(std::string("rs_h"), hash); auto k = std::make_tuple(std::string("rs_h"), hash);
bool ret = db.Exists(k); ret = db.Exists(k);
LOCK(cs); LOCK(cs);
hasSigForHashCache.emplace(hash, std::make_pair(ret, t)); hasSigForHashCache.insert(hash, ret);
return ret; return ret;
} }
@ -167,34 +158,9 @@ void CRecoveredSigsDb::WriteRecoveredSig(const llmq::CRecoveredSig& recSig)
int64_t t = GetTimeMillis(); int64_t t = GetTimeMillis();
LOCK(cs); LOCK(cs);
hasSigForIdCache[std::make_pair((Consensus::LLMQType)recSig.llmqType, recSig.id)] = std::make_pair(true, t); hasSigForIdCache.insert(std::make_pair((Consensus::LLMQType)recSig.llmqType, recSig.id), true);
hasSigForSessionCache[signHash] = std::make_pair(true, t); hasSigForSessionCache.insert(signHash, true);
hasSigForHashCache[recSig.GetHash()] = std::make_pair(true, t); hasSigForHashCache.insert(recSig.GetHash(), true);
}
}
template<typename K, typename H>
static void TruncateCacheMap(std::unordered_map<K, std::pair<bool, int64_t>, H>& m, size_t maxSize, size_t truncateThreshold)
{
typedef typename std::unordered_map<K, std::pair<bool, int64_t>, H> Map;
typedef typename Map::iterator Iterator;
if (m.size() <= truncateThreshold) {
return;
}
std::vector<Iterator> vec;
vec.reserve(m.size());
for (auto it = m.begin(); it != m.end(); ++it) {
vec.emplace_back(it);
}
// sort by last access time (descending order)
std::sort(vec.begin(), vec.end(), [](const Iterator& it1, const Iterator& it2) {
return it1->second.second > it2->second.second;
});
for (size_t i = maxSize; i < vec.size(); i++) {
m.erase(vec[i]);
} }
} }
@ -257,10 +223,6 @@ void CRecoveredSigsDb::CleanupOldRecoveredSigs(int64_t maxAge)
hasSigForSessionCache.erase(signHash); hasSigForSessionCache.erase(signHash);
hasSigForHashCache.erase(recSig.GetHash()); hasSigForHashCache.erase(recSig.GetHash());
} }
TruncateCacheMap(hasSigForIdCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD);
TruncateCacheMap(hasSigForSessionCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD);
TruncateCacheMap(hasSigForHashCache, MAX_CACHE_SIZE, MAX_CACHE_TRUNCATE_THRESHOLD);
} }
for (auto& e : toDelete2) { for (auto& e : toDelete2) {

View File

@ -10,6 +10,7 @@
#include "net.h" #include "net.h"
#include "chainparams.h" #include "chainparams.h"
#include "saltedhasher.h" #include "saltedhasher.h"
#include "unordered_lru_cache.h"
#include <unordered_map> #include <unordered_map>
@ -68,16 +69,13 @@ public:
class CRecoveredSigsDb class CRecoveredSigsDb
{ {
static const size_t MAX_CACHE_SIZE = 30000;
static const size_t MAX_CACHE_TRUNCATE_THRESHOLD = 50000;
private: private:
CDBWrapper& db; CDBWrapper& db;
CCriticalSection cs; CCriticalSection cs;
std::unordered_map<std::pair<Consensus::LLMQType, uint256>, std::pair<bool, int64_t>, StaticSaltedHasher> hasSigForIdCache; unordered_lru_cache<std::pair<Consensus::LLMQType, uint256>, bool, StaticSaltedHasher, 30000> hasSigForIdCache;
std::unordered_map<uint256, std::pair<bool, int64_t>, StaticSaltedHasher> hasSigForSessionCache; unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForSessionCache;
std::unordered_map<uint256, std::pair<bool, int64_t>, StaticSaltedHasher> hasSigForHashCache; unordered_lru_cache<uint256, bool, StaticSaltedHasher, 30000> hasSigForHashCache;
public: public:
CRecoveredSigsDb(CDBWrapper& _db); CRecoveredSigsDb(CDBWrapper& _db);