From 93253c27620647deb3cb60e2666fbf7db9eff4cb Mon Sep 17 00:00:00 2001 From: antirez Date: Mon, 24 Mar 2014 12:00:20 +0100 Subject: [PATCH] Sample and cache RSS in serverCron(). Obtaining the RSS (Resident Set Size) info is slow in Linux and OSX. This slowed down the generation of the INFO 'memory' section. Since the RSS does not require to be a real-time measurement, we now sample it with server.hz frequency (10 times per second by default) and use this value both to show the INFO rss field and to compute the fragmentation ratio. Practically this does not make any difference for memory profiling of Redis but speeds up the INFO call significantly. --- src/redis.c | 8 ++++++-- src/redis.h | 1 + src/zmalloc.c | 4 ++-- src/zmalloc.h | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/redis.c b/src/redis.c index 308168251..bcdba13d8 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1062,6 +1062,9 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { if (zmalloc_used_memory() > server.stat_peak_memory) server.stat_peak_memory = zmalloc_used_memory(); + /* Sample the RSS here since this is a relatively slow call. */ + server.resident_set_size = zmalloc_get_rss(); + /* We received a SIGTERM, shutting down here in a safe way, as it is * not ok doing so inside the signal handler. */ if (server.shutdown_asap) { @@ -1690,6 +1693,7 @@ void initServer() { /* A few stats we don't want to reset: server startup time, and peak mem. */ server.stat_starttime = time(NULL); server.stat_peak_memory = 0; + server.resident_set_size = 0; server.lastbgsave_status = REDIS_OK; server.aof_last_write_status = REDIS_OK; server.aof_last_write_errno = 0; @@ -2459,11 +2463,11 @@ sds genRedisInfoString(char *section) { "mem_allocator:%s\r\n", zmalloc_used, hmem, - zmalloc_get_rss(), + server.resident_set_size, server.stat_peak_memory, peak_hmem, ((long long)lua_gc(server.lua,LUA_GCCOUNT,0))*1024LL, - zmalloc_get_fragmentation_ratio(), + zmalloc_get_fragmentation_ratio(server.resident_set_size), ZMALLOC_LIB ); } diff --git a/src/redis.h b/src/redis.h index 5ac794948..fd5dac19c 100644 --- a/src/redis.h +++ b/src/redis.h @@ -676,6 +676,7 @@ struct redisServer { long long slowlog_entry_id; /* SLOWLOG current entry ID */ long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */ unsigned long slowlog_max_len; /* SLOWLOG max number of items logged */ + size_t resident_set_size; /* RSS sampled in serverCron(). */ /* The following two are used to track instantaneous "load" in terms * of operations per second. */ long long ops_sec_last_sample_time; /* Timestamp of last sample (in ms) */ diff --git a/src/zmalloc.c b/src/zmalloc.c index e7e97aa67..d0cf726cb 100644 --- a/src/zmalloc.c +++ b/src/zmalloc.c @@ -321,8 +321,8 @@ size_t zmalloc_get_rss(void) { #endif /* Fragmentation = RSS / allocated-bytes */ -float zmalloc_get_fragmentation_ratio(void) { - return (float)zmalloc_get_rss()/zmalloc_used_memory(); +float zmalloc_get_fragmentation_ratio(size_t rss) { + return (float)rss/zmalloc_used_memory(); } #if defined(HAVE_PROC_SMAPS) diff --git a/src/zmalloc.h b/src/zmalloc.h index 331d8e433..72a4f8138 100644 --- a/src/zmalloc.h +++ b/src/zmalloc.h @@ -73,7 +73,7 @@ char *zstrdup(const char *s); size_t zmalloc_used_memory(void); void zmalloc_enable_thread_safeness(void); void zmalloc_set_oom_handler(void (*oom_handler)(size_t)); -float zmalloc_get_fragmentation_ratio(void); +float zmalloc_get_fragmentation_ratio(size_t rss); size_t zmalloc_get_rss(void); size_t zmalloc_get_private_dirty(void); void zlibc_free(void *ptr);