diff options
author | dormando <dormando@rydia.net> | 2016-06-23 15:22:15 -0700 |
---|---|---|
committer | dormando <dormando@rydia.net> | 2016-06-24 00:56:55 -0700 |
commit | 31541b371a79ead88d0f57cfa6c54958d819371c (patch) | |
tree | a49676b9eef84c55218a34e2d7297db7c537be98 /slabs.c | |
parent | 8d82383f0fc82b79975cd6e16d462b8ff0d2dd39 (diff) | |
download | memcached-31541b371a79ead88d0f57cfa6c54958d819371c.tar.gz |
cache_memlimit command for tuning runtime maxbytes
Allows dynamically increasing the memory limit of a running system, if memory
isn't being preallocated.
If `-o modern` is in use, can also dynamically lower memory usage. pages are
free()'ed back to the OS via the slab rebalancer as memory is freed up. Does
not guarantee the OS will actually give the memory back for other applications
to use, that depends on how the OS handles memory.
Diffstat (limited to 'slabs.c')
-rw-r--r-- | slabs.c | 38 |
1 files changed, 38 insertions, 0 deletions
@@ -446,6 +446,22 @@ static void *memory_allocate(size_t size) { return ret; } +/* Must only be used if all pages are item_size_max */ +static void memory_release() { + void *p = NULL; + if (mem_base != NULL) + return; + + if (!settings.slab_reassign) + return; + + while (mem_malloced > mem_limit && + (p = get_page_from_global_pool()) != NULL) { + free(p); + mem_malloced -= settings.item_size_max; + } +} + void *slabs_alloc(size_t size, unsigned int id, unsigned int *total_chunks, unsigned int flags) { void *ret; @@ -468,6 +484,25 @@ void slabs_stats(ADD_STAT add_stats, void *c) { pthread_mutex_unlock(&slabs_lock); } +static bool do_slabs_adjust_mem_limit(size_t new_mem_limit) { + /* Cannot adjust memory limit at runtime if prealloc'ed */ + if (mem_base != NULL) + return false; + settings.maxbytes = new_mem_limit; + mem_limit = new_mem_limit; + mem_limit_reached = false; /* Will reset on next alloc */ + memory_release(); /* free what might already be in the global pool */ + return true; +} + +bool slabs_adjust_mem_limit(size_t new_mem_limit) { + bool ret; + pthread_mutex_lock(&slabs_lock); + ret = do_slabs_adjust_mem_limit(new_mem_limit); + pthread_mutex_unlock(&slabs_lock); + return ret; +} + void slabs_adjust_mem_requested(unsigned int id, size_t old, size_t ntotal) { pthread_mutex_lock(&slabs_lock); @@ -812,6 +847,9 @@ static void slab_rebalance_finish(void) { memset(slab_rebal.slab_start, 0, (size_t)settings.item_size_max); split_slab_page_into_freelist(slab_rebal.slab_start, slab_rebal.d_clsid); + } else if (slab_rebal.d_clsid == SLAB_GLOBAL_PAGE_POOL) { + /* mem_malloc'ed might be higher than mem_limit. */ + memory_release(); } slab_rebal.done = 0; |