diff --git a/src/config.c b/src/config.c index 82ed333419..563d9d3c3e 100644 --- a/src/config.c +++ b/src/config.c @@ -2509,18 +2509,18 @@ static int updateReplBacklogSize(const char **err) { return 1; } -/* Adjusts `maxmemory_reserved_scale` to ensure it remains within the valid range of 10 to 60, if set. - * Once adjusted, the available memory is recalculated to reflect the new reserved memory. */ -static int updateMaxmemoryReserved(const char **err) { +/* Adjusts `maxmemory_soft_scale` to ensure it remains within the valid range of 10 to 60, if set. + * Once adjusted, the available memory is recalculated to reflect the new soft maxmemory. */ +static int updateMaxmemorySoftScale(const char **err) { UNUSED(err); - if (server.maxmemory_reserved_scale) { - if (server.maxmemory_reserved_scale < 10) { - server.maxmemory_reserved_scale = 10; - } else if (server.maxmemory_reserved_scale > 60) { - server.maxmemory_reserved_scale = 60; + if (server.maxmemory_soft_scale) { + if (server.maxmemory_soft_scale < 10) { + server.maxmemory_soft_scale = 10; + } else if (server.maxmemory_soft_scale > 60) { + server.maxmemory_soft_scale = 60; } } - updateMaxAvailableMemory(); + updateSoftMaxmemoryValue(); return 1; } @@ -2535,7 +2535,7 @@ static int updateMaxmemory(const char **err) { "depending on the maxmemory-policy.", server.maxmemory, used); } - updateMaxAvailableMemory(); + updateSoftMaxmemoryValue(); startEvictionTimeProc(); } return 1; @@ -3235,7 +3235,7 @@ standardConfig static_configs[] = { createIntConfig("lfu-decay-time", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.lfu_decay_time, 1, INTEGER_CONFIG, NULL, NULL), createIntConfig("replica-priority", "slave-priority", MODIFIABLE_CONFIG, 0, INT_MAX, server.replica_priority, 100, INTEGER_CONFIG, NULL, NULL), createIntConfig("repl-diskless-sync-delay", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.repl_diskless_sync_delay, 5, INTEGER_CONFIG, NULL, NULL), - createIntConfig("maxmemory-reserved-scale", NULL, MODIFIABLE_CONFIG, 0, 100, server.maxmemory_reserved_scale, 0, INTEGER_CONFIG, NULL, updateMaxmemoryReserved), + createIntConfig("maxmemory-soft-scale", NULL, MODIFIABLE_CONFIG, 0, 100, server.maxmemory_soft_scale, 0, INTEGER_CONFIG, NULL, updateMaxmemorySoftScale), createIntConfig("maxmemory-samples", NULL, MODIFIABLE_CONFIG, 1, 64, server.maxmemory_samples, 5, INTEGER_CONFIG, NULL, NULL), createIntConfig("maxmemory-eviction-tenacity", NULL, MODIFIABLE_CONFIG, 0, 100, server.maxmemory_eviction_tenacity, 10, INTEGER_CONFIG, NULL, NULL), createIntConfig("timeout", NULL, MODIFIABLE_CONFIG, 0, INT_MAX, server.maxidletime, 0, INTEGER_CONFIG, NULL, NULL), /* Default client timeout: infinite */ diff --git a/src/evict.c b/src/evict.c index a2c95f0d70..acbd9f58d2 100644 --- a/src/evict.c +++ b/src/evict.c @@ -398,12 +398,12 @@ int getMaxmemoryState(size_t *total, size_t *logical, size_t *tofree, float *lev if (total) *total = mem_reported; /* We may return ASAP if there is no need to compute the level. */ - if (!server.maxmemory_available) { + if (!server.maxmemory_soft) { if (level) *level = 0; return C_OK; } - if (mem_reported <= server.maxmemory_available && !level) return C_OK; + if (mem_reported <= server.maxmemory_soft && !level) return C_OK; /* Remove the size of replicas output buffers and AOF buffer from the * count of used memory. */ @@ -416,13 +416,13 @@ int getMaxmemoryState(size_t *total, size_t *logical, size_t *tofree, float *lev *level = (float)mem_used / (float)server.maxmemory; } - if (mem_reported <= server.maxmemory_available) return C_OK; + if (mem_reported <= server.maxmemory_soft) return C_OK; /* Check if we are still over the memory limit. */ - if (mem_used <= server.maxmemory_available) return C_OK; + if (mem_used <= server.maxmemory_soft) return C_OK; /* Compute how much memory we need to free. */ - mem_tofree = mem_used - server.maxmemory_available; + mem_tofree = mem_used - server.maxmemory_soft; if (logical) *logical = mem_used; if (tofree) *tofree = mem_tofree; @@ -729,7 +729,7 @@ int performEvictions(void) { } } /* at this point, the memory is OK, or we have reached the time limit */ - if (server.maxmemory_reserved_scale && server.maxmemory_available) { + if (server.maxmemory_soft_scale) { size_t mem_used = zmalloc_used_memory(); size_t overhead = freeMemoryGetNotCountedMemory(); mem_used = (mem_used > overhead) ? mem_used - overhead : 0; @@ -740,7 +740,6 @@ int performEvictions(void) { } result = (isEvictionProcRunning) ? EVICT_RUNNING : EVICT_OK; - cant_free: if (result == EVICT_FAIL) { /* At this point, we have run out of evictable items. It's possible diff --git a/src/server.c b/src/server.c index fb069e75cb..8a800c744f 100644 --- a/src/server.c +++ b/src/server.c @@ -2712,7 +2712,7 @@ void initServer(void) { resetReplicationBuffer(); if (server.maxmemory) { - updateMaxAvailableMemory(); + updateSoftMaxmemoryValue(); } /* Make sure the locale is set on startup based on the config file. */ @@ -5625,7 +5625,7 @@ sds genValkeyInfoString(dict *section_dict, int all_sections, int everything) { char used_memory_scripts_hmem[64]; char used_memory_rss_hmem[64]; char maxmemory_hmem[64]; - char maxmemory_available_hmem[64]; + char maxmemory_soft_hmem[64]; size_t zmalloc_used = zmalloc_used_memory(); size_t total_system_mem = server.system_memory_size; const char *evict_policy = evictPolicyToString(); @@ -5647,7 +5647,7 @@ sds genValkeyInfoString(dict *section_dict, int all_sections, int everything) { bytesToHuman(used_memory_scripts_hmem, sizeof(used_memory_scripts_hmem), mh->lua_caches + mh->functions_caches); bytesToHuman(used_memory_rss_hmem, sizeof(used_memory_rss_hmem), server.cron_malloc_stats.process_rss); bytesToHuman(maxmemory_hmem, sizeof(maxmemory_hmem), server.maxmemory); - bytesToHuman(maxmemory_available_hmem, sizeof(maxmemory_available_hmem), server.maxmemory_available); + bytesToHuman(maxmemory_soft_hmem, sizeof(maxmemory_soft_hmem), server.maxmemory_soft); if (sections++) info = sdscat(info, "\r\n"); info = sdscatprintf( @@ -5686,9 +5686,9 @@ sds genValkeyInfoString(dict *section_dict, int all_sections, int everything) { "maxmemory:%lld\r\n", server.maxmemory, "maxmemory_human:%s\r\n", maxmemory_hmem, "maxmemory_policy:%s\r\n", evict_policy, - "maxmemory_reserved_scale:%d\r\n", server.maxmemory_reserved_scale, - "maxmemory_available:%lld\r\n", server.maxmemory_available, - "maxmemory_available_human:%s\r\n", maxmemory_available_hmem, + "maxmemory_soft_scale:%d\r\n", server.maxmemory_soft_scale, + "maxmemory_soft:%lld\r\n", server.maxmemory_soft, + "maxmemory_soft_human:%s\r\n", maxmemory_soft_hmem, "allocator_frag_ratio:%.2f\r\n", mh->allocator_frag, "allocator_frag_bytes:%zu\r\n", mh->allocator_frag_bytes, "allocator_rss_ratio:%.2f\r\n", mh->allocator_rss, diff --git a/src/server.h b/src/server.h index 4b478322e6..fa5f07b656 100644 --- a/src/server.h +++ b/src/server.h @@ -2097,8 +2097,8 @@ struct valkeyServer { ssize_t maxmemory_clients; /* Memory limit for total client buffers */ int maxmemory_policy; /* Policy for key eviction */ int maxmemory_samples; /* Precision of random sampling */ - int maxmemory_reserved_scale; /* Percent of the maxmemory value */ - unsigned long long maxmemory_available; /* Max memory to store data */ + int maxmemory_soft_scale; /* Percent of the soft maxmemory value */ + unsigned long long maxmemory_soft; /* Soft maxmemory value to store data */ int maxmemory_eviction_tenacity; /* Aggressiveness of eviction processing */ int lfu_log_factor; /* LFU logarithmic counter factor. */ int lfu_decay_time; /* LFU counter decay factor. */ @@ -3033,8 +3033,8 @@ void trimStringObjectIfNeeded(robj *o, int trim_small_values); static inline int canUseSharedObject(void) { return server.maxmemory == 0 || !(server.maxmemory_policy & MAXMEMORY_FLAG_NO_SHARED_INTEGERS); } -static inline void updateMaxAvailableMemory(void) { - server.maxmemory_available = (unsigned long long)server.maxmemory / 100.0 * (100 - server.maxmemory_reserved_scale); +static inline void updateSoftMaxmemoryValue(void) { + server.maxmemory_soft = (unsigned long long)server.maxmemory / 100.0 * (100 - server.maxmemory_soft_scale); } #define sdsEncodedObject(objptr) (objptr->encoding == OBJ_ENCODING_RAW || objptr->encoding == OBJ_ENCODING_EMBSTR) diff --git a/tests/unit/maxmemory.tcl b/tests/unit/maxmemory.tcl index 72855b0e8b..1b2edc15ee 100644 --- a/tests/unit/maxmemory.tcl +++ b/tests/unit/maxmemory.tcl @@ -146,13 +146,13 @@ start_server {tags {"maxmemory" "external:skip"}} { start_server {tags {"maxmemory external:skip"}} { - test "maxmemory-reserved-scale" { + test "maxmemory-soft-scale" { r flushdb r config set maxmemory 10mb set current_dbsize 0 foreach scale_value {30 10 0} { - r config set maxmemory-reserved-scale $scale_value + r config set maxmemory-soft-scale $scale_value # fill 20mb using 200 keys of 100kb catch { for {set j 0} {$j < 200} {incr j} { r setrange $j 100000 x diff --git a/valkey.conf b/valkey.conf index 5244f21cfb..343cc4eec1 100644 --- a/valkey.conf +++ b/valkey.conf @@ -1192,6 +1192,13 @@ acllog-max-len 128 # # maxmemory-policy noeviction +# `maxmemory-soft-scale` defines a "soft" maxmemory threshold as a scale of the `maxmemory` limit. +# When memory usage exceeds this scale, Valkey begins proactive key eviction. However, exceeding this +# threshold does not immediately reject new write commands; only the hard `maxmemory` limit will do so. +# This scale is specified as a percentage of `maxmemory`, with a valid range between 10 and 60. +# +# maxmemory-soft-scale 0 + # LRU, LFU and minimal TTL algorithms are not precise algorithms but approximated # algorithms (in order to save memory), so you can tune it for speed or # accuracy. By default the server will check five keys and pick the one that was @@ -1248,13 +1255,6 @@ acllog-max-len 128 # in the system. It's a tradeoff between memory, CPU and latency. # # active-expire-effort 1 -# -# This parameter allows Valkey to evict keys earlier. The value represents -# a percentage of the maxmemory limit, indicating how much memory the Valkey instance reserves -# without storing data. -# The default is 0, and the value can be set between 10 and 60. -# -# maxmemory-reserved-scale 0 ############################# LAZY FREEING ####################################