From f41cc87088c502c3837567a563c44eb752f8c0d6 Mon Sep 17 00:00:00 2001 From: Ozan Tezcan Date: Thu, 13 Jan 2022 12:36:03 +0300 Subject: [PATCH] Added RM_MonotonicMicroseconds() API to provide monotonic time function (#10101) Added RM_MonotonicMicroseconds(). Modules can use monotonic timestamp counter for measurements. --- src/module.c | 6 ++++++ src/redismodule.h | 2 ++ tests/modules/misc.c | 10 ++++++++++ tests/unit/moduleapi/misc.tcl | 5 +++++ 4 files changed, 23 insertions(+) diff --git a/src/module.c b/src/module.c index 6cc9c2b0e..90ea2df7d 100644 --- a/src/module.c +++ b/src/module.c @@ -1326,6 +1326,11 @@ long long RM_Milliseconds(void) { return mstime(); } +/* Return counter of micro-seconds relative to an arbitrary point in time. */ +uint64_t RM_MonotonicMicroseconds(void) { + return getMonotonicUs(); +} + /* Mark a point in time that will be used as the start time to calculate * the elapsed execution time when RM_BlockedClientMeasureTimeEnd() is called. * Within the same command, you can call multiple times @@ -10599,6 +10604,7 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(GetBlockedClientPrivateData); REGISTER_API(AbortBlock); REGISTER_API(Milliseconds); + REGISTER_API(MonotonicMicroseconds); REGISTER_API(BlockedClientMeasureTimeStart); REGISTER_API(BlockedClientMeasureTimeEnd); REGISTER_API(GetThreadSafeContext); diff --git a/src/redismodule.h b/src/redismodule.h index 0f8ab6fb2..4ce342338 100644 --- a/src/redismodule.h +++ b/src/redismodule.h @@ -837,6 +837,7 @@ REDISMODULE_API int (*RedisModule_GetToDbIdFromOptCtx)(RedisModuleKeyOptCtx *ctx REDISMODULE_API const RedisModuleString * (*RedisModule_GetKeyNameFromOptCtx)(RedisModuleKeyOptCtx *ctx) REDISMODULE_ATTR; REDISMODULE_API const RedisModuleString * (*RedisModule_GetToKeyNameFromOptCtx)(RedisModuleKeyOptCtx *ctx) REDISMODULE_ATTR; REDISMODULE_API long long (*RedisModule_Milliseconds)(void) REDISMODULE_ATTR; +REDISMODULE_API uint64_t (*RedisModule_MonotonicMicroseconds)(void) REDISMODULE_ATTR; REDISMODULE_API void (*RedisModule_DigestAddStringBuffer)(RedisModuleDigest *md, unsigned char *ele, size_t len) REDISMODULE_ATTR; REDISMODULE_API void (*RedisModule_DigestAddLongLong)(RedisModuleDigest *md, long long ele) REDISMODULE_ATTR; REDISMODULE_API void (*RedisModule_DigestEndSequence)(RedisModuleDigest *md) REDISMODULE_ATTR; @@ -1154,6 +1155,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int REDISMODULE_GET_API(GetDbIdFromOptCtx); REDISMODULE_GET_API(GetToDbIdFromOptCtx); REDISMODULE_GET_API(Milliseconds); + REDISMODULE_GET_API(MonotonicMicroseconds); REDISMODULE_GET_API(DigestAddStringBuffer); REDISMODULE_GET_API(DigestAddLongLong); REDISMODULE_GET_API(DigestEndSequence); diff --git a/tests/modules/misc.c b/tests/modules/misc.c index 94b4754ad..db9c090d4 100644 --- a/tests/modules/misc.c +++ b/tests/modules/misc.c @@ -302,6 +302,14 @@ int test_weird_cmd(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { return REDISMODULE_OK; } +int test_monotonic_time(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { + REDISMODULE_NOT_USED(argv); + REDISMODULE_NOT_USED(argc); + + RedisModule_ReplyWithLongLong(ctx, RedisModule_MonotonicMicroseconds()); + return REDISMODULE_OK; +} + int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) { REDISMODULE_NOT_USED(argv); REDISMODULE_NOT_USED(argc); @@ -341,6 +349,8 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) /* Add a command with ':' in it's name, so that we can check commandstats sanitization. */ if (RedisModule_CreateCommand(ctx,"test.weird:cmd", test_weird_cmd,"readonly",0,0,0) == REDISMODULE_ERR) return REDISMODULE_ERR; + if (RedisModule_CreateCommand(ctx,"test.monotonic_time", test_monotonic_time,"",0,0,0) == REDISMODULE_ERR) + return REDISMODULE_ERR; return REDISMODULE_OK; } diff --git a/tests/unit/moduleapi/misc.tcl b/tests/unit/moduleapi/misc.tcl index 091de4a87..9aa191814 100644 --- a/tests/unit/moduleapi/misc.tcl +++ b/tests/unit/moduleapi/misc.tcl @@ -128,4 +128,9 @@ start_server {tags {"modules"}} { set info [r info commandstats] assert_match {*cmdstat_test.weird_cmd:calls=1*} $info } + + test {test monotonic time} { + set x [r test.monotonic_time] + assert { [r test.monotonic_time] >= $x } + } }