From 4bbb2b01523efe40068258d0265fff1802868d43 Mon Sep 17 00:00:00 2001 From: erpeng Date: Tue, 31 Oct 2023 15:57:26 +0800 Subject: [PATCH] Optimize CPU cache efficiency on dict while it's being rehashed (#5692) when find a key ,if redis is rehashing, currently we should lookup both tables (ht[0] and ht[1]). if we use the key's index comparing to the rehashidx,if index < rehashidx,then we can conclude: 1. it is rehashing(rehashidx is -1 if it is not rehashing) 2. we can't find key in ht[0] so just continue to find key in ht[1] The possible performance gain here, is not the looping over the linked list (which is empty), but rather the lookup in the table (which could be a cache miss). --------- Co-authored-by: zhangshihua003 Co-authored-by: sundb Co-authored-by: Oran Agra Co-authored-by: judeng --- src/dict.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/dict.c b/src/dict.c index cc7ea1b53..1946e2492 100644 --- a/src/dict.c +++ b/src/dict.c @@ -563,6 +563,7 @@ static dictEntry *dictGenericDelete(dict *d, const void *key, int nofree) { for (table = 0; table <= 1; table++) { idx = h & DICTHT_SIZE_MASK(d->ht_size_exp[table]); + if (table == 0 && (long)idx < d->rehashidx) continue; he = d->ht_table[table][idx]; prevHe = NULL; while(he) { @@ -672,6 +673,7 @@ dictEntry *dictFind(dict *d, const void *key) h = dictHashKey(d, key); for (table = 0; table <= 1; table++) { idx = h & DICTHT_SIZE_MASK(d->ht_size_exp[table]); + if (table == 0 && (long)idx < d->rehashidx) continue; he = d->ht_table[table][idx]; while(he) { void *he_key = dictGetKey(he); @@ -1450,6 +1452,7 @@ void *dictFindPositionForInsert(dict *d, const void *key, dictEntry **existing) return NULL; for (table = 0; table <= 1; table++) { idx = hash & DICTHT_SIZE_MASK(d->ht_size_exp[table]); + if (table == 0 && (long)idx < d->rehashidx) continue; /* Search if this slot does not already contain the given key */ he = d->ht_table[table][idx]; while(he) { @@ -1496,6 +1499,7 @@ dictEntry *dictFindEntryByPtrAndHash(dict *d, const void *oldptr, uint64_t hash) if (dictSize(d) == 0) return NULL; /* dict is empty */ for (table = 0; table <= 1; table++) { idx = hash & DICTHT_SIZE_MASK(d->ht_size_exp[table]); + if (table == 0 && (long)idx < d->rehashidx) continue; he = d->ht_table[table][idx]; while(he) { if (oldptr == dictGetKey(he))