diff --git a/src/debug.c b/src/debug.c index c625ab5150..94890d4620 100644 --- a/src/debug.c +++ b/src/debug.c @@ -864,7 +864,7 @@ void debugCommand(client *c) { 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)dictEntryMemUsage()); + sizes = sdscatprintf(sizes, "dictentry:%d ", (int)dictEntryMemUsage(NULL)); 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/dict.c b/src/dict.c index ac6744dbbf..0776929171 100644 --- a/src/dict.c +++ b/src/dict.c @@ -968,8 +968,15 @@ size_t dictMemUsage(const dict *d) { return dictSize(d) * sizeof(dictEntry) + dictBuckets(d) * sizeof(dictEntry *); } -size_t dictEntryMemUsage(void) { - return sizeof(dictEntry); +/* Returns the memory usage in bytes of dictEntry based on the type. if `de` is NULL, return the size of + * regular dict entry else return based on the type. */ +size_t dictEntryMemUsage(dictEntry *de) { + if (de == NULL || entryIsNormal(de)) return sizeof(dictEntry); + else if (entryIsKey(de)) return 0; + else if (entryIsNoValue(de)) return sizeof(dictEntryNoValue); + else if (entryIsEmbedded(de)) return zmalloc_size(decodeEmbeddedEntry(de)); + else assert("Entry type not supported"); + return 0; } /* A fingerprint is a 64 bit number that represents the state of the dictionary diff --git a/src/dict.h b/src/dict.h index 2baba3b1cb..6f0eef8371 100644 --- a/src/dict.h +++ b/src/dict.h @@ -220,7 +220,7 @@ uint64_t dictGetUnsignedIntegerVal(const dictEntry *de); double dictGetDoubleVal(const dictEntry *de); double *dictGetDoubleValPtr(dictEntry *de); size_t dictMemUsage(const dict *d); -size_t dictEntryMemUsage(void); +size_t dictEntryMemUsage(dictEntry *de); dictIterator *dictGetIterator(dict *d); dictIterator *dictGetSafeIterator(dict *d); void dictInitIterator(dictIterator *iter, dict *d); diff --git a/src/kvstore.c b/src/kvstore.c index afe3d3d733..00d2d7a58f 100644 --- a/src/kvstore.c +++ b/src/kvstore.c @@ -340,7 +340,7 @@ size_t kvstoreMemUsage(kvstore *kvs) { size_t mem = sizeof(*kvs); unsigned long long keys_count = kvstoreSize(kvs); - mem += keys_count * dictEntryMemUsage() + kvstoreBuckets(kvs) * sizeof(dictEntry *) + + mem += keys_count * dictEntryMemUsage(NULL) + kvstoreBuckets(kvs) * sizeof(dictEntry *) + kvs->allocated_dicts * (sizeof(dict) + kvstoreDictMetadataSize(NULL)); /* Values are dict* shared with kvs->dicts */ diff --git a/src/object.c b/src/object.c index f1b5e27d13..b366984d06 100644 --- a/src/object.c +++ b/src/object.c @@ -1010,7 +1010,7 @@ size_t objectComputeSize(robj *key, robj *o, size_t sample_size, int dbid) { asize = sizeof(*o) + sizeof(dict) + (sizeof(struct dictEntry *) * dictBuckets(d)); while ((de = dictNext(di)) != NULL && samples < sample_size) { ele = dictGetKey(de); - elesize += dictEntryMemUsage() + sdsZmallocSize(ele); + elesize += dictEntryMemUsage(de) + sdsZmallocSize(ele); samples++; } dictReleaseIterator(di); @@ -1033,7 +1033,7 @@ size_t objectComputeSize(robj *key, robj *o, size_t sample_size, int dbid) { (sizeof(struct dictEntry *) * dictBuckets(d)) + zmalloc_size(zsl->header); while (znode != NULL && samples < sample_size) { elesize += sdsZmallocSize(znode->ele); - elesize += dictEntryMemUsage() + zmalloc_size(znode); + elesize += dictEntryMemUsage(NULL) + zmalloc_size(znode); samples++; znode = znode->level[0].forward; } @@ -1052,7 +1052,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 += dictEntryMemUsage(); + elesize += dictEntryMemUsage(de); samples++; } dictReleaseIterator(di); @@ -1552,7 +1552,7 @@ NULL return; } size_t usage = objectComputeSize(c->argv[2], dictGetVal(de), samples, c->db->id); - usage += zmalloc_size(de); + usage += dictEntryMemUsage(de); addReplyLongLong(c, usage); } else if (!strcasecmp(c->argv[1]->ptr, "stats") && c->argc == 2) { struct serverMemOverhead *mh = getMemoryOverheadData();