Skip to content

Commit

Permalink
Accurate dictEntry memory usage calculation
Browse files Browse the repository at this point in the history
Signed-off-by: Harkrishn Patro <[email protected]>
  • Loading branch information
hpatro committed Jun 27, 2024
1 parent e714f2c commit 4d30109
Show file tree
Hide file tree
Showing 5 changed files with 16 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
11 changes: 9 additions & 2 deletions src/dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/kvstore.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
8 changes: 4 additions & 4 deletions src/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand All @@ -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);
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 4d30109

Please sign in to comment.