From c84248b5d2fba04e5056bad32a5d29a5fc906e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20S=C3=B6derqvist?= Date: Wed, 11 Jan 2023 09:57:10 +0100 Subject: [PATCH] Make dictEntry opaque Use functions for all accesses to dictEntry (except in dict.c). Dict abuses e.g. in defrag.c have been replaced by support functions provided by dict. --- src/cluster.c | 6 +-- src/config.c | 8 ++-- src/db.c | 9 ++-- src/debug.c | 2 +- src/defrag.c | 61 ++++++++++++++------------- src/dict.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++ src/dict.h | 76 +++++++++++----------------------- src/eval.c | 4 +- src/expire.c | 6 +-- src/functions.c | 7 ++-- src/object.c | 14 +++---- src/pubsub.c | 6 +-- src/redis-cli.c | 2 +- src/t_zset.c | 5 ++- 14 files changed, 195 insertions(+), 119 deletions(-) diff --git a/src/cluster.c b/src/cluster.c index 71c45d742..ecebc511b 100644 --- a/src/cluster.c +++ b/src/cluster.c @@ -7288,7 +7288,7 @@ int clusterRedirectBlockedClientIfNeeded(client *c) { * understand if we have keys for a given hash slot. */ void slotToKeyAddEntry(dictEntry *entry, redisDb *db) { - sds key = entry->key; + sds key = dictGetKey(entry); unsigned int hashslot = keyHashSlot(key, sdslen(key)); slotToKeys *slot_to_keys = &(*db->slots_to_keys).by_slot[hashslot]; slot_to_keys->count++; @@ -7305,7 +7305,7 @@ void slotToKeyAddEntry(dictEntry *entry, redisDb *db) { } void slotToKeyDelEntry(dictEntry *entry, redisDb *db) { - sds key = entry->key; + sds key = dictGetKey(entry); unsigned int hashslot = keyHashSlot(key, sdslen(key)); slotToKeys *slot_to_keys = &(*db->slots_to_keys).by_slot[hashslot]; slot_to_keys->count--; @@ -7337,7 +7337,7 @@ void slotToKeyReplaceEntry(dictEntry *entry, redisDb *db) { dictEntryNextInSlot(prev) = entry; } else { /* The replaced entry was the first in the list. */ - sds key = entry->key; + sds key = dictGetKey(entry); unsigned int hashslot = keyHashSlot(key, sdslen(key)); slotToKeys *slot_to_keys = &(*db->slots_to_keys).by_slot[hashslot]; slot_to_keys->head = entry; diff --git a/src/config.c b/src/config.c index 90baed9ee..9de4ecd41 100644 --- a/src/config.c +++ b/src/config.c @@ -989,8 +989,8 @@ void configGetCommand(client *c) { /* Note that hidden configs require an exact match (not a pattern) */ if (config->flags & HIDDEN_CONFIG) continue; if (dictFind(matches, config->name)) continue; - if (stringmatch(name, de->key, 1)) { - dictAdd(matches, de->key, config); + if (stringmatch(name, dictGetKey(de), 1)) { + dictAdd(matches, dictGetKey(de), config); } } dictReleaseIterator(di); @@ -1000,7 +1000,7 @@ void configGetCommand(client *c) { addReplyMapLen(c, dictSize(matches)); while ((de = dictNext(di)) != NULL) { standardConfig *config = (standardConfig *) dictGetVal(de); - addReplyBulkCString(c, de->key); + addReplyBulkCString(c, dictGetKey(de)); addReplyBulkSds(c, config->interface.get(config)); } dictReleaseIterator(di); @@ -1754,7 +1754,7 @@ int rewriteConfig(char *path, int force_write) { standardConfig *config = dictGetVal(de); /* Only rewrite the primary names */ if (config->flags & ALIAS_CONFIG) continue; - if (config->interface.rewrite) config->interface.rewrite(config, de->key, state); + if (config->interface.rewrite) config->interface.rewrite(config, dictGetKey(de), state); } dictReleaseIterator(di); diff --git a/src/db.c b/src/db.c index aad822630..abe717ace 100644 --- a/src/db.c +++ b/src/db.c @@ -228,7 +228,6 @@ static void dbSetValue(redisDb *db, robj *key, robj *val, int overwrite) { dictEntry *de = dictFind(db->dict,key->ptr); serverAssertWithInfo(NULL,key,de != NULL); - dictEntry auxentry = *de; robj *old = dictGetVal(de); if (server.maxmemory_policy & MAXMEMORY_FLAG_LFU) { val->lru = old->lru; @@ -246,17 +245,15 @@ static void dbSetValue(redisDb *db, robj *key, robj *val, int overwrite) { decrRefCount(old); /* Because of RM_StringDMA, old may be changed, so we need get old again */ old = dictGetVal(de); - /* Entry in auxentry may be changed, so we need update auxentry */ - auxentry = *de; } dictSetVal(db->dict, de, val); if (server.lazyfree_lazy_server_del) { freeObjAsync(key,old,db->id); - dictSetVal(db->dict, &auxentry, NULL); + } else { + /* This is just decrRefCount(old); */ + db->dict->type->valDestructor(db->dict, old); } - - dictFreeVal(db->dict, &auxentry); } /* Replace an existing key with a new value, we just replace value and don't diff --git a/src/debug.c b/src/debug.c index c9495e5d8..fe46b5c62 100644 --- a/src/debug.c +++ b/src/debug.c @@ -868,7 +868,7 @@ NULL sds sizes = sdsempty(); sizes = sdscatprintf(sizes,"bits:%d ",(sizeof(void*) == 8)?64:32); sizes = sdscatprintf(sizes,"robj:%d ",(int)sizeof(robj)); - sizes = sdscatprintf(sizes,"dictentry:%d ",(int)sizeof(dictEntry)); + sizes = sdscatprintf(sizes,"dictentry:%d ",(int)dictEntryMemUsage()); sizes = sdscatprintf(sizes,"sdshdr5:%d ",(int)sizeof(struct sdshdr5)); sizes = sdscatprintf(sizes,"sdshdr8:%d ",(int)sizeof(struct sdshdr8)); sizes = sdscatprintf(sizes,"sdshdr16:%d ",(int)sizeof(struct sdshdr16)); diff --git a/src/defrag.c b/src/defrag.c index dbdf2ab62..e258d38c0 100644 --- a/src/defrag.c +++ b/src/defrag.c @@ -163,7 +163,7 @@ long dictIterDefragEntry(dictIterator *iter) { if (newde) { defragged++; iter->nextEntry = newde; - iter->entry->next = newde; + dictSetNext(iter->entry, newde); } } /* handle the case of the first entry in the hash bucket. */ @@ -264,7 +264,7 @@ long activeDefragZsetEntry(zset *zs, dictEntry *de) { long defragged = 0; sds sdsele = dictGetKey(de); if ((newsds = activeDefragSds(sdsele))) - defragged++, de->key = newsds; + defragged++, dictSetKey(zs->dict, de, newsds); newscore = zslDefrag(zs->zsl, *(double*)dictGetVal(de), sdsele, newsds); if (newscore) { dictSetVal(zs->dict, de, newscore); @@ -288,24 +288,24 @@ long activeDefragSdsDict(dict* d, int val_type) { while((de = dictNext(di)) != NULL) { sds sdsele = dictGetKey(de), newsds; if ((newsds = activeDefragSds(sdsele))) - de->key = newsds, defragged++; + dictSetKey(d, de, newsds), defragged++; /* defrag the value */ if (val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) { sdsele = dictGetVal(de); if ((newsds = activeDefragSds(sdsele))) - de->v.val = newsds, defragged++; + dictSetVal(d, de, newsds), defragged++; } else if (val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) { robj *newele, *ele = dictGetVal(de); if ((newele = activeDefragStringOb(ele, &defragged))) - de->v.val = newele; + dictSetVal(d, de, newele); } else if (val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) { void *newptr, *ptr = dictGetVal(de); if ((newptr = activeDefragAlloc(ptr))) - de->v.val = newptr, defragged++; + dictSetVal(d, de, newptr), defragged++; } else if (val_type == DEFRAG_SDS_DICT_VAL_LUA_SCRIPT) { void *newptr, *ptr = dictGetVal(de); if ((newptr = activeDefragLuaScript(ptr, &defragged))) - de->v.val = newptr; + dictSetVal(d, de, newptr); } defragged += dictIterDefragEntry(di); } @@ -374,7 +374,7 @@ long activeDefragSdsListAndDict(list *l, dict *d, int dict_val_type) { uint64_t hash = dictGetHash(d, newsds); dictEntry **deref = dictFindEntryRefByPtrAndHash(d, sdsele, hash); if (deref) - (*deref)->key = newsds; + dictSetKey(d, *deref, newsds); ln->value = newsds; defragged++; } @@ -386,15 +386,15 @@ long activeDefragSdsListAndDict(list *l, dict *d, int dict_val_type) { if (dict_val_type == DEFRAG_SDS_DICT_VAL_IS_SDS) { sds newsds, sdsele = dictGetVal(de); if ((newsds = activeDefragSds(sdsele))) - de->v.val = newsds, defragged++; + dictSetVal(d, de, newsds), defragged++; } else if (dict_val_type == DEFRAG_SDS_DICT_VAL_IS_STROB) { robj *newele, *ele = dictGetVal(de); if ((newele = activeDefragStringOb(ele, &defragged))) - de->v.val = newele; + dictSetVal(d, de, newele); } else if (dict_val_type == DEFRAG_SDS_DICT_VAL_VOID_PTR) { void *newptr, *ptr = dictGetVal(de); if ((newptr = activeDefragAlloc(ptr))) - de->v.val = newptr, defragged++; + dictSetVal(d, de, newptr), defragged++; } defragged += dictIterDefragEntry(di); } @@ -420,7 +420,7 @@ dictEntry* replaceSatelliteDictKeyPtrAndOrDefragDictEntry(dict *d, sds oldkey, s (*defragged)++; } if (newkey) - de->key = newkey; + dictSetKey(d, de, newkey); return de; } return NULL; @@ -531,43 +531,48 @@ long scanLaterZset(robj *ob, unsigned long *cursor) { return data.defragged; } +typedef struct { + dict *dict; + long defragged; +} scanLaterDictData; + void scanLaterSetCallback(void *privdata, const dictEntry *_de) { dictEntry *de = (dictEntry*)_de; - long *defragged = privdata; + scanLaterDictData *data = privdata; sds sdsele = dictGetKey(de), newsds; if ((newsds = activeDefragSds(sdsele))) - (*defragged)++, de->key = newsds; + data->defragged++, dictSetKey(data->dict, de, newsds); server.stat_active_defrag_scanned++; } long scanLaterSet(robj *ob, unsigned long *cursor) { - long defragged = 0; if (ob->type != OBJ_SET || ob->encoding != OBJ_ENCODING_HT) return 0; dict *d = ob->ptr; - *cursor = dictScan(d, *cursor, scanLaterSetCallback, defragDictBucketCallback, &defragged); - return defragged; + scanLaterDictData data = {d, 0}; + *cursor = dictScan(d, *cursor, scanLaterSetCallback, defragDictBucketCallback, &data); + return data.defragged; } void scanLaterHashCallback(void *privdata, const dictEntry *_de) { dictEntry *de = (dictEntry*)_de; - long *defragged = privdata; + scanLaterDictData *data = privdata; sds sdsele = dictGetKey(de), newsds; if ((newsds = activeDefragSds(sdsele))) - (*defragged)++, de->key = newsds; + data->defragged++, dictSetKey(data->dict, de, newsds); sdsele = dictGetVal(de); if ((newsds = activeDefragSds(sdsele))) - (*defragged)++, de->v.val = newsds; + data->defragged++, dictSetVal(data->dict, de, newsds); server.stat_active_defrag_scanned++; } long scanLaterHash(robj *ob, unsigned long *cursor) { - long defragged = 0; if (ob->type != OBJ_HASH || ob->encoding != OBJ_ENCODING_HT) return 0; dict *d = ob->ptr; - *cursor = dictScan(d, *cursor, scanLaterHashCallback, defragDictBucketCallback, &defragged); - return defragged; + scanLaterDictData data = {d, 0}; + *cursor = dictScan(d, *cursor, scanLaterHashCallback, defragDictBucketCallback, &data); + return data.defragged; } long defragQuicklist(redisDb *db, dictEntry *kde) { @@ -847,19 +852,19 @@ long defragKey(redisDb *db, dictEntry *de) { /* Try to defrag the key name. */ newsds = activeDefragSds(keysds); if (newsds) - defragged++, de->key = newsds; + defragged++, dictSetKey(db->dict, de, newsds); if (dictSize(db->expires)) { /* Dirty code: * I can't search in db->expires for that key after i already released * the pointer it holds it won't be able to do the string compare */ - uint64_t hash = dictGetHash(db->dict, de->key); + uint64_t hash = dictGetHash(db->dict, dictGetKey(de)); replaceSatelliteDictKeyPtrAndOrDefragDictEntry(db->expires, keysds, newsds, hash, &defragged); } /* Try to defrag robj and / or string value. */ ob = dictGetVal(de); if ((newob = activeDefragStringOb(ob, &defragged))) { - de->v.val = newob; + dictSetVal(db->dict, de, newob); ob = newob; } @@ -928,7 +933,7 @@ void defragScanCallback(void *privdata, const dictEntry *de) { /* Defrag scan callback for each hash table bucket, * used in order to defrag the dictEntry allocations. */ void defragDictBucketCallback(dict *d, dictEntry **bucketref) { - while(*bucketref) { + while (bucketref && *bucketref) { dictEntry *de = *bucketref, *newde; if ((newde = activeDefragAlloc(de))) { *bucketref = newde; @@ -937,7 +942,7 @@ void defragDictBucketCallback(dict *d, dictEntry **bucketref) { slotToKeyReplaceEntry(newde, server.db); } } - bucketref = &(*bucketref)->next; + bucketref = dictGetNextRef(*bucketref); } } diff --git a/src/dict.c b/src/dict.c index 90fd4f52e..418c42bbb 100644 --- a/src/dict.c +++ b/src/dict.c @@ -58,6 +58,22 @@ static dictResizeEnable dict_can_resize = DICT_RESIZE_ENABLE; static unsigned int dict_force_resize_ratio = 5; +/* -------------------------- types ----------------------------------------- */ + +struct dictEntry { + void *key; + union { + void *val; + uint64_t u64; + int64_t s64; + double d; + } v; + struct dictEntry *next; /* Next entry in the same hash bucket. */ + void *metadata[]; /* An arbitrary number of bytes (starting at a + * pointer-aligned address) of size as returned + * by dictType's dictEntryMetadataBytes(). */ +}; + /* -------------------------- private prototypes ---------------------------- */ static int _dictExpandIfNeeded(dict *d); @@ -596,6 +612,98 @@ void dictTwoPhaseUnlinkFree(dict *d, dictEntry *he, dictEntry **plink, int table dictResumeRehashing(d); } +void dictSetKey(dict *d, dictEntry* de, void *key) { + if (d->type->keyDup) + de->key = d->type->keyDup(d, key); + else + de->key = key; +} + +void dictSetVal(dict *d, dictEntry *de, void *val) { + de->v.val = d->type->valDup ? d->type->valDup(d, val) : val; +} + +void dictSetSignedIntegerVal(dictEntry *de, int64_t val) { + de->v.s64 = val; +} + +void dictSetUnsignedIntegerVal(dictEntry *de, uint64_t val) { + de->v.u64 = val; +} + +void dictSetDoubleVal(dictEntry *de, double val) { + de->v.d = val; +} + +int64_t dictIncrSignedIntegerVal(dictEntry *de, int64_t val) { + return de->v.s64 += val; +} + +uint64_t dictIncrUnsignedIntegerVal(dictEntry *de, uint64_t val) { + return de->v.u64 += val; +} + +double dictIncrDoubleVal(dictEntry *de, double val) { + return de->v.d += val; +} + +/* Only used when the next in hash bucket has been reallocated. */ +void dictSetNext(dictEntry *de, dictEntry *next) { + de->next = next; +} + +/* A pointer to the metadata section within the dict entry. */ +void *dictMetadata(dictEntry *de) { + return &de->metadata; +} + +void *dictGetKey(const dictEntry *de) { + return de->key; +} + +void *dictGetVal(const dictEntry *de) { + return de->v.val; +} + +int64_t dictGetSignedIntegerVal(const dictEntry *de) { + return de->v.s64; +} + +uint64_t dictGetUnsignedIntegerVal(const dictEntry *de) { + return de->v.u64; +} + +double dictGetDoubleVal(const dictEntry *de) { + return de->v.d; +} + +/* Returns a mutable reference to the value as a double within the entry. */ +double *dictGetDoubleValPtr(dictEntry *de) { + return &de->v.d; +} + +/* The next entry in same hash bucket. */ +dictEntry *dictGetNext(const dictEntry *de) { + return de->next; +} + +/* A pointer to the 'next' field within the entry, or NULL if there is no next + * field. */ +dictEntry **dictGetNextRef(dictEntry *de) { + return &de->next; +} + +/* Returns the memory usage in bytes of the dict, excluding the size of the keys + * and values. */ +size_t dictMemUsage(const dict *d) { + return dictSize(d) * sizeof(dictEntry) + + dictSlots(d) * sizeof(dictEntry*); +} + +size_t dictEntryMemUsage(void) { + return sizeof(dictEntry); +} + /* A fingerprint is a 64 bit number that represents the state of the dictionary * at a given time, it's just a few dict properties xored together. * When an unsafe iterator is initialized, we get the dict fingerprint, and check diff --git a/src/dict.h b/src/dict.h index 00b721d3d..a7ee282da 100644 --- a/src/dict.h +++ b/src/dict.h @@ -44,19 +44,7 @@ #define DICT_OK 0 #define DICT_ERR 1 -typedef struct dictEntry { - void *key; - union { - void *val; - uint64_t u64; - int64_t s64; - double d; - } v; - struct dictEntry *next; /* Next entry in the same hash bucket. */ - void *metadata[]; /* An arbitrary number of bytes (starting at a - * pointer-aligned address) of size as returned - * by dictType's dictEntryMetadataBytes(). */ -} dictEntry; +typedef struct dictEntry dictEntry; /* opaque */ typedef struct dict dict; @@ -112,60 +100,22 @@ typedef void (dictScanBucketFunction)(dict *d, dictEntry **bucketref); /* ------------------------------- Macros ------------------------------------*/ #define dictFreeVal(d, entry) do { \ if ((d)->type->valDestructor) \ - (d)->type->valDestructor((d), (entry)->v.val); \ + (d)->type->valDestructor((d), dictGetVal(entry)); \ } while(0) -#define dictSetVal(d, entry, _val_) do { \ - if ((d)->type->valDup) \ - (entry)->v.val = (d)->type->valDup((d), _val_); \ - else \ - (entry)->v.val = (_val_); \ -} while(0) - -#define dictSetSignedIntegerVal(entry, _val_) \ - do { (entry)->v.s64 = _val_; } while(0) - -#define dictSetUnsignedIntegerVal(entry, _val_) \ - do { (entry)->v.u64 = _val_; } while(0) - -#define dictSetDoubleVal(entry, _val_) \ - do { (entry)->v.d = _val_; } while(0) - -#define dictIncrSignedIntegerVal(entry, _val_) \ - ((entry)->v.s64 += _val_) - -#define dictIncrUnsignedIntegerVal(entry, _val_) \ - ((entry)->v.u64 += _val_) - -#define dictIncrDoubleVal(entry, _val_) \ - ((entry)->v.d += _val_) - #define dictFreeKey(d, entry) \ if ((d)->type->keyDestructor) \ - (d)->type->keyDestructor((d), (entry)->key) - -#define dictSetKey(d, entry, _key_) do { \ - if ((d)->type->keyDup) \ - (entry)->key = (d)->type->keyDup((d), _key_); \ - else \ - (entry)->key = (_key_); \ -} while(0) + (d)->type->keyDestructor((d), dictGetKey(entry)) #define dictCompareKeys(d, key1, key2) \ (((d)->type->keyCompare) ? \ (d)->type->keyCompare((d), key1, key2) : \ (key1) == (key2)) -#define dictMetadata(entry) (&(entry)->metadata) #define dictMetadataSize(d) ((d)->type->dictEntryMetadataBytes \ ? (d)->type->dictEntryMetadataBytes(d) : 0) #define dictHashKey(d, key) ((d)->type->hashFunction(key)) -#define dictGetKey(he) ((he)->key) -#define dictGetVal(he) ((he)->v.val) -#define dictGetSignedIntegerVal(he) ((he)->v.s64) -#define dictGetUnsignedIntegerVal(he) ((he)->v.u64) -#define dictGetDoubleVal(he) ((he)->v.d) #define dictSlots(d) (DICTHT_SIZE((d)->ht_size_exp[0])+DICTHT_SIZE((d)->ht_size_exp[1])) #define dictSize(d) ((d)->ht_used[0]+(d)->ht_used[1]) #define dictIsRehashing(d) ((d)->rehashidx != -1) @@ -202,6 +152,26 @@ void dictRelease(dict *d); dictEntry * dictFind(dict *d, const void *key); void *dictFetchValue(dict *d, const void *key); int dictResize(dict *d); +void dictSetKey(dict *d, dictEntry* de, void *key); +void dictSetVal(dict *d, dictEntry *de, void *val); +void dictSetSignedIntegerVal(dictEntry *de, int64_t val); +void dictSetUnsignedIntegerVal(dictEntry *de, uint64_t val); +void dictSetDoubleVal(dictEntry *de, double val); +int64_t dictIncrSignedIntegerVal(dictEntry *de, int64_t val); +uint64_t dictIncrUnsignedIntegerVal(dictEntry *de, uint64_t val); +double dictIncrDoubleVal(dictEntry *de, double val); +void dictSetNext(dictEntry *de, dictEntry *next); +void *dictMetadata(dictEntry *de); +void *dictGetKey(const dictEntry *de); +void *dictGetVal(const dictEntry *de); +int64_t dictGetSignedIntegerVal(const dictEntry *de); +uint64_t dictGetUnsignedIntegerVal(const dictEntry *de); +double dictGetDoubleVal(const dictEntry *de); +double *dictGetDoubleValPtr(dictEntry *de); +dictEntry *dictGetNext(const dictEntry *de); +dictEntry **dictGetNextRef(dictEntry *de); +size_t dictMemUsage(const dict *d); +size_t dictEntryMemUsage(void); dictIterator *dictGetIterator(dict *d); dictIterator *dictGetSafeIterator(dict *d); void dictInitIterator(dictIterator *iter, dict *d); diff --git a/src/eval.c b/src/eval.c index 6eb6ed1d4..1fa08c9dd 100644 --- a/src/eval.c +++ b/src/eval.c @@ -677,8 +677,8 @@ dict* evalScriptsDict() { unsigned long evalScriptsMemory() { return lctx.lua_scripts_mem + - dictSize(lctx.lua_scripts) * (sizeof(dictEntry) + sizeof(luaScript)) + - dictSlots(lctx.lua_scripts) * sizeof(dictEntry*); + dictMemUsage(lctx.lua_scripts) + + dictSize(lctx.lua_scripts) * sizeof(luaScript); } /* --------------------------------------------------------------------------- diff --git a/src/expire.c b/src/expire.c index 7b6b3bc9c..d819dad37 100644 --- a/src/expire.c +++ b/src/expire.c @@ -258,7 +258,7 @@ void activeExpireCycle(int type) { /* Get the next entry now since this entry may get * deleted. */ dictEntry *e = de; - de = de->next; + de = dictGetNext(de); ttl = dictGetSignedIntegerVal(e)-now; if (activeExpireCycleTryExpire(db,e,now)) { @@ -444,8 +444,8 @@ void rememberSlaveKeyWithExpire(redisDb *db, robj *key) { * representing the key: we don't want to need to take those keys * in sync with the main DB. The keys will be removed by expireSlaveKeys() * as it scans to find keys to remove. */ - if (de->key == key->ptr) { - de->key = sdsdup(key->ptr); + if (dictGetKey(de) == key->ptr) { + dictSetKey(slaveKeysWithExpire, de, sdsdup(key->ptr)); dictSetUnsignedIntegerVal(de,0); } diff --git a/src/functions.c b/src/functions.c index 3f7b3a7ef..c60d40d3c 100644 --- a/src/functions.c +++ b/src/functions.c @@ -1091,10 +1091,9 @@ unsigned long functionsMemory() { /* Return memory overhead of all the engines combine */ unsigned long functionsMemoryOverhead() { - size_t memory_overhead = dictSize(engines) * sizeof(dictEntry) + - dictSlots(engines) * sizeof(dictEntry*); - memory_overhead += dictSize(curr_functions_lib_ctx->functions) * sizeof(dictEntry) + - dictSlots(curr_functions_lib_ctx->functions) * sizeof(dictEntry*) + sizeof(functionsLibCtx); + size_t memory_overhead = dictMemUsage(engines); + memory_overhead += dictMemUsage(curr_functions_lib_ctx->functions); + memory_overhead += sizeof(functionsLibCtx); memory_overhead += curr_functions_lib_ctx->cache_memory; memory_overhead += engine_cache_memory; diff --git a/src/object.c b/src/object.c index 54ed57958..ca9a24088 100644 --- a/src/object.c +++ b/src/object.c @@ -1029,7 +1029,7 @@ size_t objectComputeSize(robj *key, robj *o, size_t sample_size, int dbid) { asize = sizeof(*o)+sizeof(dict)+(sizeof(struct dictEntry*)*dictSlots(d)); while((de = dictNext(di)) != NULL && samples < sample_size) { ele = dictGetKey(de); - elesize += sizeof(struct dictEntry) + sdsZmallocSize(ele); + elesize += dictEntryMemUsage() + sdsZmallocSize(ele); samples++; } dictReleaseIterator(di); @@ -1053,7 +1053,7 @@ size_t objectComputeSize(robj *key, robj *o, size_t sample_size, int dbid) { zmalloc_size(zsl->header); while(znode != NULL && samples < sample_size) { elesize += sdsZmallocSize(znode->ele); - elesize += sizeof(struct dictEntry)+zmalloc_size(znode); + elesize += dictEntryMemUsage()+zmalloc_size(znode); samples++; znode = znode->level[0].forward; } @@ -1072,7 +1072,7 @@ size_t objectComputeSize(robj *key, robj *o, size_t sample_size, int dbid) { ele = dictGetKey(de); ele2 = dictGetVal(de); elesize += sdsZmallocSize(ele) + sdsZmallocSize(ele2); - elesize += sizeof(struct dictEntry); + elesize += dictEntryMemUsage(); samples++; } dictReleaseIterator(di); @@ -1242,14 +1242,12 @@ struct redisMemOverhead *getMemoryOverheadData(void) { mh->db = zrealloc(mh->db,sizeof(mh->db[0])*(mh->num_dbs+1)); mh->db[mh->num_dbs].dbid = j; - mem = dictSize(db->dict) * sizeof(dictEntry) + - dictSlots(db->dict) * sizeof(dictEntry*) + + mem = dictMemUsage(db->dict) + dictSize(db->dict) * sizeof(robj); mh->db[mh->num_dbs].overhead_ht_main = mem; mem_total+=mem; - mem = dictSize(db->expires) * sizeof(dictEntry) + - dictSlots(db->expires) * sizeof(dictEntry*); + mem = dictMemUsage(db->expires); mh->db[mh->num_dbs].overhead_ht_expires = mem; mem_total+=mem; @@ -1547,7 +1545,7 @@ NULL } size_t usage = objectComputeSize(c->argv[2],dictGetVal(de),samples,c->db->id); usage += sdsZmallocSize(dictGetKey(de)); - usage += sizeof(dictEntry); + usage += dictEntryMemUsage(); usage += dictMetadataSize(c->db->dict); addReplyLongLong(c,usage); } else if (!strcasecmp(c->argv[1]->ptr,"stats") && c->argc == 2) { diff --git a/src/pubsub.c b/src/pubsub.c index 2e2522c57..a257a8af3 100644 --- a/src/pubsub.c +++ b/src/pubsub.c @@ -727,10 +727,8 @@ size_t pubsubMemOverhead(client *c) { /* PubSub patterns */ size_t mem = listLength(c->pubsub_patterns) * sizeof(listNode); /* Global PubSub channels */ - mem += dictSize(c->pubsub_channels) * sizeof(dictEntry) + - dictSlots(c->pubsub_channels) * sizeof(dictEntry*); + mem += dictMemUsage(c->pubsub_channels); /* Sharded PubSub channels */ - mem += dictSize(c->pubsubshard_channels) * sizeof(dictEntry) + - dictSlots(c->pubsubshard_channels) * sizeof(dictEntry*); + mem += dictMemUsage(c->pubsubshard_channels); return mem; } diff --git a/src/redis-cli.c b/src/redis-cli.c index c8576702c..b9d84c6d9 100644 --- a/src/redis-cli.c +++ b/src/redis-cli.c @@ -762,7 +762,7 @@ void cliInitGroupHelpEntries(dict *groups) { for (entry = dictNext(iter); entry != NULL; entry = dictNext(iter)) { tmp.argc = 1; tmp.argv = zmalloc(sizeof(sds)); - tmp.argv[0] = sdscatprintf(sdsempty(),"@%s",(char *)entry->key); + tmp.argv[0] = sdscatprintf(sdsempty(),"@%s",(char *)dictGetKey(entry)); tmp.full = tmp.argv[0]; tmp.type = CLI_HELP_GROUP; tmp.org.name = NULL; diff --git a/src/t_zset.c b/src/t_zset.c index 048759d1f..5dadd58fd 100644 --- a/src/t_zset.c +++ b/src/t_zset.c @@ -1428,7 +1428,7 @@ int zsetAdd(robj *zobj, double score, sds ele, int in_flags, int *out_flags, dou /* Note that we did not removed the original element from * the hash table representing the sorted set, so we just * update the score. */ - dictGetVal(de) = &znode->score; /* Update score ptr. */ + dictSetVal(zs->dict, de, &znode->score); /* Update score ptr. */ *out_flags |= ZADD_OUT_UPDATED; } return 1; @@ -2741,7 +2741,8 @@ void zunionInterDiffGenericCommand(client *c, robj *dstkey, int numkeysIndex, in * Here we access directly the dictEntry double * value inside the union as it is a big speedup * compared to using the getDouble/setDouble API. */ - zunionInterAggregate(&existing->v.d,score,aggregate); + double *existing_score_ptr = dictGetDoubleValPtr(existing); + zunionInterAggregate(existing_score_ptr, score, aggregate); } } zuiClearIterator(&src[i]);