diff --git a/src/config.c b/src/config.c index 05cb7c9f..c4c4ec69 100644 --- a/src/config.c +++ b/src/config.c @@ -226,6 +226,10 @@ void loadServerConfigFromString(char *config) { } } else if (!strcasecmp(argv[0],"maxmemory") && argc == 2) { server.maxmemory = memtoll(argv[1],NULL); + } else if (!strcasecmp(argv[0],"rss-aware-maxmemory") && argc==2) { + if ((server.rss_aware_maxmemory = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } } else if (!strcasecmp(argv[0],"maxmemory-policy") && argc == 2) { if (!strcasecmp(argv[1],"volatile-lru")) { server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU; @@ -637,6 +641,11 @@ void configSetCommand(redisClient *c) { } freeMemoryIfNeeded(); } + } else if (!strcasecmp(c->argv[2]->ptr,"rss-aware-maxmemory")) { + int yn = yesnotoi(o->ptr); + + if (yn == -1) goto badfmt; + server.rss_aware_maxmemory = yn; } else if (!strcasecmp(c->argv[2]->ptr,"maxclients")) { int orig_value = server.maxclients; @@ -1093,6 +1102,8 @@ void configGetCommand(redisClient *c) { server.aof_rewrite_incremental_fsync); config_get_bool_field("aof-load-truncated", server.aof_load_truncated); + config_get_bool_field("rss-aware-maxmemory", + server.rss_aware_maxmemory); /* Everything we can't handle with macros follows. */ diff --git a/src/config.h b/src/config.h index 57d07599..adbfc88d 100644 --- a/src/config.h +++ b/src/config.h @@ -48,11 +48,13 @@ #define HAVE_PROC_STAT 1 #define HAVE_PROC_MAPS 1 #define HAVE_PROC_SMAPS 1 +#define HAVE_RSS_REPORTING 1 #endif /* Test for task_info() */ #if defined(__APPLE__) #define HAVE_TASKINFO 1 +#define HAVE_RSS_REPORTING 1 #endif /* Test for backtrace() */ diff --git a/src/redis.c b/src/redis.c index 83e0946e..929dcace 100644 --- a/src/redis.c +++ b/src/redis.c @@ -1435,6 +1435,9 @@ void initServerConfig(void) { server.maxmemory = REDIS_DEFAULT_MAXMEMORY; server.maxmemory_policy = REDIS_DEFAULT_MAXMEMORY_POLICY; server.maxmemory_samples = REDIS_DEFAULT_MAXMEMORY_SAMPLES; + server.rss_aware_maxmemory = REDIS_DEFAULT_RSS_AWARE_MAXMEMORY; + server.maxmemory_enforced = 0; + server.maxmemory_adjusted = 0; server.hash_max_ziplist_entries = REDIS_HASH_MAX_ZIPLIST_ENTRIES; server.hash_max_ziplist_value = REDIS_HASH_MAX_ZIPLIST_VALUE; server.list_max_ziplist_entries = REDIS_LIST_MAX_ZIPLIST_ENTRIES; diff --git a/src/redis.h b/src/redis.h index 855ae574..b047c13a 100644 --- a/src/redis.h +++ b/src/redis.h @@ -121,6 +121,7 @@ typedef long long mstime_t; /* millisecond time type. */ #define REDIS_DEFAULT_REPL_DISABLE_TCP_NODELAY 0 #define REDIS_DEFAULT_MAXMEMORY 0 #define REDIS_DEFAULT_MAXMEMORY_SAMPLES 5 +#define REDIS_DEFAULT_RSS_AWARE_MAXMEMORY 0 #define REDIS_DEFAULT_AOF_FILENAME "appendonly.aof" #define REDIS_DEFAULT_AOF_NO_FSYNC_ON_REWRITE 0 #define REDIS_DEFAULT_AOF_LOAD_TRUNCATED 1 @@ -839,6 +840,14 @@ struct redisServer { unsigned long long maxmemory; /* Max number of memory bytes to use */ int maxmemory_policy; /* Policy for key eviction */ int maxmemory_samples; /* Pricision of random sampling */ + /* RSS aware maxmemory additional state: + * the adjusted maxmemory is adjusted for fragmentation, however we + * enforce maxmemory_enforced instead, which follows the adjusted value + * in small steps at eviction cycle to avoid too fast changes in the + * enforced maxmemory value. */ + int rss_aware_maxmemory; /* Non zero if enabled. */ + unsigned long long maxmemory_adjusted; /* Maxmemory adjusted for frag. */ + unsigned long long maxmemory_enforced; /* Currently enforced maxmemory. */ /* Blocked clients */ unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */ list *unblocked_clients; /* list of clients to unblock before next loop */