Speedup keyIsExpired by removing subkey search

Former-commit-id: a01564158e40300ab4a0338c0a6e924972385407
This commit is contained in:
Malavan 2021-05-07 09:40:23 +00:00
parent 9a2d6cbad2
commit bafd03f53c
4 changed files with 31 additions and 16 deletions

View File

@ -1626,17 +1626,9 @@ int keyIsExpired(redisDb *db, robj *key) {
/* Don't expire anything while loading. It will be done later. */
if (g_pserver->loading) return 0;
long long when = -1;
for (auto &exp : *pexpire)
{
if (exp.subkey() == nullptr)
{
when = exp.when();
break;
}
}
long long when = pexpire->whenFull();
if (when == -1)
if (when == INVALID_EXPIRE)
return 0;
/* If we are in the context of a Lua script, we pretend that time is

View File

@ -153,7 +153,7 @@ int activeExpireCycleExpire(redisDb *db, expireEntry &e, long long now, size_t &
pfat->popfrontExpireEntry();
fTtlChanged = true;
if ((tried % ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP) == 0) {
if ((tried % ACTIVE_EXPIRE_CYCLE_SUBKEY_LOOKUPS_PER_LOOP) == 0) {
break;
}
}

View File

@ -1,5 +1,7 @@
#pragma once
#define INVALID_EXPIRE LLONG_MIN
class expireEntryFat
{
friend class expireEntry;
@ -31,6 +33,14 @@ public:
~expireEntryFat();
long long when() const noexcept { return m_vecexpireEntries.front().when; }
long long whenFull() const noexcept {
for (size_t i = 0; i < size(); ++i) {
if (m_vecexpireEntries[i].spsubkey == nullptr) {
return m_vecexpireEntries[i].when;
}
}
return INVALID_EXPIRE;
}
const char *key() const noexcept { return m_keyPrimary; }
bool operator<(long long when) const noexcept { return this->when() < when; }
@ -51,7 +61,7 @@ class expireEntry {
expireEntryFat *m_pfatentry;
} u;
long long m_when; // LLONG_MIN means this is a fat entry and we should use the pointer
long long m_whenFull;
public:
class iter
{
@ -91,7 +101,8 @@ public:
{
if (subkey != nullptr)
{
m_when = LLONG_MIN;
m_when = INVALID_EXPIRE;
m_whenFull = INVALID_EXPIRE;
u.m_pfatentry = new (MALLOC_LOCAL) expireEntryFat(key);
u.m_pfatentry->expireSubKey(subkey, when);
}
@ -99,19 +110,22 @@ public:
{
u.m_key = key;
m_when = when;
m_whenFull = when;
}
}
expireEntry(expireEntryFat *pfatentry)
{
u.m_pfatentry = pfatentry;
m_when = LLONG_MIN;
m_when = INVALID_EXPIRE;
m_whenFull = pfatentry->whenFull();
}
expireEntry(expireEntry &&e)
{
u.m_key = e.u.m_key;
m_when = e.m_when;
m_whenFull = e.m_whenFull;
e.u.m_key = (char*)key(); // we do this so it can still be found in the set
e.m_when = 0;
}
@ -130,7 +144,7 @@ public:
u.m_key = key;
}
inline bool FFat() const noexcept { return m_when == LLONG_MIN; }
inline bool FFat() const noexcept { return m_when == INVALID_EXPIRE; }
expireEntryFat *pfatentry() { assert(FFat()); return u.m_pfatentry; }
@ -160,9 +174,17 @@ public:
return u.m_pfatentry->when();
return m_when;
}
long long whenFull() const noexcept
{
return m_whenFull;
}
void update(const char *subkey, long long when)
{
if (subkey == nullptr)
{
m_whenFull = when;
}
if (!FFat())
{
if (subkey == nullptr)
@ -175,7 +197,7 @@ public:
// we have to upgrade to a fat entry
long long whenT = m_when;
sds keyPrimary = u.m_key;
m_when = LLONG_MIN;
m_when = INVALID_EXPIRE;
u.m_pfatentry = new (MALLOC_LOCAL) expireEntryFat(keyPrimary);
u.m_pfatentry->expireSubKey(nullptr, whenT);
// at this point we're fat so fall through

View File

@ -303,6 +303,7 @@ inline bool operator!=(const void *p, const robj_sharedptr &rhs)
#define CONFIG_DEFAULT_ENABLE_MULTIMASTER 0
#define ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 64 /* Loopkups per loop. */
#define ACTIVE_EXPIRE_CYCLE_SUBKEY_LOOKUPS_PER_LOOP 16384 /* Subkey loopkups per loop. */
#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds */
#define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* CPU max % for keys collection */
#define ACTIVE_EXPIRE_CYCLE_SLOW 0