From 61bb04415614f4b99002cc6c6a31ef5019881b07 Mon Sep 17 00:00:00 2001 From: Hanna Fadida Date: Sun, 17 Oct 2021 17:31:06 +0300 Subject: [PATCH] Modify mem_usage2 module callback to enable to take sample_size argument (#9612) This is useful for approximating size computation of complex module types. Note that the mem_usage2 callback is new and has not been released yet, which is why we can modify it. --- src/module.c | 15 ++++++++------- src/object.c | 4 ++-- src/redismodule.h | 2 +- src/server.h | 4 ++-- tests/modules/datatype2.c | 3 ++- 5 files changed, 15 insertions(+), 13 deletions(-) diff --git a/src/module.c b/src/module.c index 8507e0264..0cdad7eac 100644 --- a/src/module.c +++ b/src/module.c @@ -5227,13 +5227,14 @@ robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj * NOTE: The value is passed as a `void**` and the function is expected to update the * pointer if the top-level value pointer is defragmented and consequently changes. * - * * **mem_usage2**: Similar to `mem_usage`, but provides the `RedisModuleKeyOptCtx` parameter + * * **mem_usage2**: Similar to `mem_usage`, but provides the `RedisModuleKeyOptCtx` parameter + * so that meta information such as key name and db id can be obtained, and + * the `sample_size` for size estimation (see MEMORY USAGE command). + * * **free_effort2**: Similar to `free_effort`, but provides the `RedisModuleKeyOptCtx` parameter * so that meta information such as key name and db id can be obtained. - * * **free_effort2**: Similar to `free_effort`, but provides the `RedisModuleKeyOptCtx` parameter + * * **unlink2**: Similar to `unlink`, but provides the `RedisModuleKeyOptCtx` parameter * so that meta information such as key name and db id can be obtained. - * * **unlink2**: Similar to `unlink`, but provides the `RedisModuleKeyOptCtx` parameter - * so that meta information such as key name and db id can be obtained. - * * **copy2**: Similar to `copy`, but provides the `RedisModuleKeyOptCtx` parameter + * * **copy2**: Similar to `copy`, but provides the `RedisModuleKeyOptCtx` parameter * so that meta information such as key names and db ids can be obtained. * * Note: the module name "AAAAAAAAA" is reserved and produces an error, it @@ -9313,14 +9314,14 @@ size_t moduleGetFreeEffort(robj *key, robj *val, int dbid) { /* Return the memory usage of the module, it will automatically choose to call * `mem_usage` or `mem_usage2`, and the default return value is 0. */ -size_t moduleGetMemUsage(robj *key, robj *val, int dbid) { +size_t moduleGetMemUsage(robj *key, robj *val, size_t sample_size, int dbid) { moduleValue *mv = val->ptr; moduleType *mt = mv->type; size_t size = 0; /* We prefer to use the enhanced version. */ if (mt->mem_usage2 != NULL) { RedisModuleKeyOptCtx ctx = {key, NULL, dbid, -1}; - size = mt->mem_usage2(&ctx,mv->value); + size = mt->mem_usage2(&ctx, mv->value, sample_size); } else if (mt->mem_usage != NULL) { size = mt->mem_usage(mv->value); } diff --git a/src/object.c b/src/object.c index edbd56acb..4c62df3f0 100644 --- a/src/object.c +++ b/src/object.c @@ -1127,7 +1127,7 @@ size_t objectComputeSize(robj *key, robj *o, size_t sample_size, int dbid) { raxStop(&ri); } } else if (o->type == OBJ_MODULE) { - asize = moduleGetMemUsage(key, o, dbid); + asize = moduleGetMemUsage(key, o, sample_size, dbid); } else { serverPanic("Unknown object type"); } @@ -1487,7 +1487,7 @@ void memoryCommand(client *c) { " Return information about the memory usage of the server.", "USAGE [SAMPLES ]", " Return memory in bytes used by and its value. Nested values are", -" sampled up to times (default: 5).", +" sampled up to times (default: 5, 0 means sample all).", NULL }; addReplyHelp(c, help); diff --git a/src/redismodule.h b/src/redismodule.h index 315789194..938bacc5c 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -543,7 +543,7 @@ typedef int (*RedisModuleTypeAuxLoadFunc)(RedisModuleIO *rdb, int encver, int wh typedef void (*RedisModuleTypeAuxSaveFunc)(RedisModuleIO *rdb, int when); typedef void (*RedisModuleTypeRewriteFunc)(RedisModuleIO *aof, RedisModuleString *key, void *value); typedef size_t (*RedisModuleTypeMemUsageFunc)(const void *value); -typedef size_t (*RedisModuleTypeMemUsageFunc2)(RedisModuleKeyOptCtx *ctx, const void *value); +typedef size_t (*RedisModuleTypeMemUsageFunc2)(RedisModuleKeyOptCtx *ctx, const void *value, size_t sample_size); typedef void (*RedisModuleTypeDigestFunc)(RedisModuleDigest *digest, void *value); typedef void (*RedisModuleTypeFreeFunc)(void *value); typedef size_t (*RedisModuleTypeFreeEffortFunc)(RedisModuleString *key, const void *value); diff --git a/src/server.h b/src/server.h index 60428843a..9ad4d78d0 100644 --- a/src/server.h +++ b/src/server.h @@ -583,7 +583,7 @@ typedef void *(*moduleTypeCopyFunc)(struct redisObject *fromkey, struct redisObj typedef int (*moduleTypeDefragFunc)(struct RedisModuleDefragCtx *ctx, struct redisObject *key, void **value); typedef void (*RedisModuleInfoFunc)(struct RedisModuleInfoCtx *ctx, int for_crash_report); typedef void (*RedisModuleDefragFunc)(struct RedisModuleDefragCtx *ctx); -typedef size_t (*moduleTypeMemUsageFunc2)(struct RedisModuleKeyOptCtx *ctx, const void *value); +typedef size_t (*moduleTypeMemUsageFunc2)(struct RedisModuleKeyOptCtx *ctx, const void *value, size_t sample_size); typedef void (*moduleTypeFreeFunc2)(struct RedisModuleKeyOptCtx *ctx, void *value); typedef size_t (*moduleTypeFreeEffortFunc2)(struct RedisModuleKeyOptCtx *ctx, const void *value); typedef void (*moduleTypeUnlinkFunc2)(struct RedisModuleKeyOptCtx *ctx, void *value); @@ -1975,7 +1975,7 @@ int moduleClientIsBlockedOnKeys(client *c); void moduleNotifyUserChanged(client *c); void moduleNotifyKeyUnlink(robj *key, robj *val, int dbid); size_t moduleGetFreeEffort(robj *key, robj *val, int dbid); -size_t moduleGetMemUsage(robj *key, robj *val, int dbid); +size_t moduleGetMemUsage(robj *key, robj *val, size_t sample_size, int dbid); robj *moduleTypeDupOrReply(client *c, robj *fromkey, robj *tokey, int todb, robj *value); int moduleDefragValue(robj *key, robj *obj, long *defragged, int dbid); int moduleLateDefrag(robj *key, robj *value, unsigned long *cursor, long long endtime, long long *defragged, int dbid); diff --git a/tests/modules/datatype2.c b/tests/modules/datatype2.c index 0c4279ae5..8ab1b2629 100644 --- a/tests/modules/datatype2.c +++ b/tests/modules/datatype2.c @@ -657,8 +657,9 @@ void *MemAllocCopy2(RedisModuleKeyOptCtx *ctx, const void *value) { return new; } -size_t MemAllocMemUsage2(RedisModuleKeyOptCtx *ctx, const void *value) { +size_t MemAllocMemUsage2(RedisModuleKeyOptCtx *ctx, const void *value, size_t sample_size) { REDISMODULE_NOT_USED(ctx); + REDISMODULE_NOT_USED(sample_size); uint64_t size = 0; MemAllocObject *o = (MemAllocObject *)value;