Skip to content

Commit deb6540

Browse files
Include background thread cpu usage info on info modules output (#439)
1 parent 573d7dd commit deb6540

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

src/redisai.c

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <string.h>
1212
#include <pthread.h>
1313
#include <sys/time.h>
14+
#include <sys/resource.h>
1415
#include <unistd.h>
1516
#include <stdbool.h>
1617
#include "backends/util.h"
@@ -1093,11 +1094,56 @@ static int RedisAI_RegisterApi(RedisModuleCtx* ctx) {
10931094
void RAI_moduleInfoFunc(RedisModuleInfoCtx *ctx, int for_crash_report) {
10941095
RedisModule_InfoAddSection(ctx, "git");
10951096
RedisModule_InfoAddFieldCString(ctx, "git_sha", REDISAI_GIT_SHA);
1096-
10971097
RedisModule_InfoAddSection(ctx, "load_time_configs");
10981098
RedisModule_InfoAddFieldLongLong(ctx, "threads_per_queue", perqueueThreadPoolSize);
10991099
RedisModule_InfoAddFieldLongLong(ctx, "inter_op_parallelism", getBackendsInterOpParallelism());
11001100
RedisModule_InfoAddFieldLongLong(ctx, "intra_op_parallelism", getBackendsIntraOpParallelism());
1101+
struct rusage self_ru, c_ru;
1102+
// Return resource usage statistics for the calling process,
1103+
// which is the sum of resources used by all threads in the
1104+
// process
1105+
getrusage(RUSAGE_SELF, &self_ru);
1106+
// Return resource usage statistics for all of its
1107+
// terminated child processes
1108+
getrusage(RUSAGE_CHILDREN, &c_ru);
1109+
sds self_used_cpu_sys = sdscatprintf(sdsempty(),"%ld.%06ld",(long)self_ru.ru_stime.tv_sec,(long)self_ru.ru_stime.tv_usec);
1110+
sds self_used_cpu_user = sdscatprintf(sdsempty(),"%ld.%06ld",(long)self_ru.ru_utime.tv_sec, (long)self_ru.ru_utime.tv_usec);
1111+
sds children_used_cpu_sys = sdscatprintf(sdsempty(),"%ld.%06ld",(long)c_ru.ru_stime.tv_sec,(long)c_ru.ru_stime.tv_usec);
1112+
sds children_used_cpu_user = sdscatprintf(sdsempty(),"%ld.%06ld",(long)c_ru.ru_utime.tv_sec, (long)c_ru.ru_utime.tv_usec);
1113+
RedisModule_InfoAddSection(ctx, "cpu");
1114+
RedisModule_InfoAddFieldCString(ctx, "self_used_cpu_sys", self_used_cpu_sys);
1115+
RedisModule_InfoAddFieldCString(ctx, "self_used_cpu_user", self_used_cpu_user);
1116+
RedisModule_InfoAddFieldCString(ctx, "children_used_cpu_sys", children_used_cpu_sys);
1117+
RedisModule_InfoAddFieldCString(ctx, "children_used_cpu_user", children_used_cpu_user);
1118+
1119+
AI_dictIterator *iter = AI_dictGetSafeIterator(run_queues);
1120+
AI_dictEntry *entry = AI_dictNext(iter);
1121+
while (entry) {
1122+
char *queue_name = (char *)AI_dictGetKey(entry);
1123+
RunQueueInfo *run_queue_info = (RunQueueInfo *)AI_dictGetVal(entry);
1124+
if(run_queue_info){
1125+
for (int i = 0; i < perqueueThreadPoolSize; i++) {
1126+
pthread_t current_bg_threads = run_queue_info->threads[i];
1127+
struct timespec ts;
1128+
clockid_t cid;
1129+
sds queue_used_cpu_total = sdscatprintf(sdsempty(),"queue_%s_bthread_#%d_used_cpu_total",queue_name,i+1);
1130+
sds bthread_used_cpu_total = sdsempty();
1131+
const int status = pthread_getcpuclockid(current_bg_threads,&cid);
1132+
if (status != 0){
1133+
bthread_used_cpu_total = sdscatprintf(bthread_used_cpu_total,"N/A");
1134+
} else {
1135+
if (clock_gettime(cid, &ts) == -1){
1136+
bthread_used_cpu_total = sdscatprintf(bthread_used_cpu_total,"N/A");
1137+
} else {
1138+
bthread_used_cpu_total = sdscatprintf(bthread_used_cpu_total,"%ld.%06ld",(long)ts.tv_sec, (long)(ts.tv_nsec / 1000000));
1139+
}
1140+
}
1141+
RedisModule_InfoAddFieldCString(ctx, queue_used_cpu_total, bthread_used_cpu_total);
1142+
}
1143+
}
1144+
entry = AI_dictNext(iter);
1145+
}
1146+
AI_dictReleaseIterator(iter);
11011147
}
11021148

11031149
int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc) {

test/tests_common.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,14 @@ def test_tensorget_disconnect(env):
291291
env.assertEqual(ret, b'OK')
292292
ret = send_and_disconnect(('AI.TENSORGET', 't_FLOAT', 'META'), red)
293293
env.assertEqual(ret, None)
294+
295+
def test_info_modules(env):
296+
red = env.getConnection()
297+
ret = red.execute_command('INFO','MODULES')
298+
env.assertEqual( ret['ai_threads_per_queue'], 1 )
299+
# minimum cpu properties
300+
env.assertEqual( 'ai_self_used_cpu_sys' in ret, True )
301+
env.assertEqual( 'ai_self_used_cpu_user' in ret, True )
302+
env.assertEqual( 'ai_children_used_cpu_sys' in ret, True )
303+
env.assertEqual( 'ai_children_used_cpu_user' in ret, True )
304+
env.assertEqual( 'ai_queue_CPU_bthread_#1_used_cpu_total' in ret, True )

0 commit comments

Comments
 (0)