mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-27 20:25:55 -04:00
chg: usr: Reduce memory footprint by actively returning unused memory to the OS
Previously, :iscman:`named` relied on the default allocator settings for releasing unused memory back to the operating system, which could result in unnecessarily high resident memory usage. :iscman:`named` now actively manages memory page purging. On systems using jemalloc, background cleanup threads are enabled and the dirty page decay time is reduced from 10 seconds to 5 seconds. Additionally, a volume-based decay pass is triggered after every 16 MiB of freed memory. On glibc-based systems, a similar volume-based mechanism using malloc_trim() is used instead. Merge branch 'ondrej/enable-background-cleaning-of-unused-memory' into 'main' See merge request isc-projects/bind9!11761
This commit is contained in:
commit
460bf794a5
2 changed files with 62 additions and 4 deletions
|
|
@ -179,7 +179,7 @@ extern isc_mem_t *isc_g_mctx;
|
|||
* see https://github.com/jemalloc/jemalloc/issues/2566
|
||||
* for more information.
|
||||
*/
|
||||
#if HAVE_JEMALLOC
|
||||
#if JEMALLOC_API_SUPPORTED
|
||||
|
||||
/*
|
||||
* cmocka.h has confliction definitions with the jemalloc header but we only
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
#include <isc/os.h>
|
||||
#include <isc/overflow.h>
|
||||
#include <isc/refcount.h>
|
||||
#include <isc/stdtime.h>
|
||||
#include <isc/strerr.h>
|
||||
#include <isc/string.h>
|
||||
#include <isc/tid.h>
|
||||
|
|
@ -81,6 +82,10 @@ isc_mem_t *isc_g_mctx = NULL;
|
|||
#define ZERO_ALLOCATION_SIZE sizeof(void *)
|
||||
#define DEBUG_TABLE_COUNT 512U
|
||||
|
||||
#ifdef JEMALLOC_API_SUPPORTED
|
||||
static ssize_t default_dirty_decay_ms = 10000;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Types.
|
||||
*/
|
||||
|
|
@ -213,8 +218,6 @@ write_size(int fd, size_t size) {
|
|||
|
||||
write_string(fd, str);
|
||||
}
|
||||
#undef TOSTRING
|
||||
#undef STRINGIFY
|
||||
|
||||
static void
|
||||
write_errno(int fd, int errnum) {
|
||||
|
|
@ -398,6 +401,38 @@ mem_get(isc_mem_t *ctx, size_t size, int flags) {
|
|||
return ptr;
|
||||
}
|
||||
|
||||
static thread_local size_t freed_bytes = 0;
|
||||
static _Atomic(isc_stdtime_t) last_purge = 0;
|
||||
|
||||
constexpr size_t purge_threshold = (16 * 1024 * 1024);
|
||||
|
||||
#if defined(JEMALLOC_API_SUPPORTED) || defined(__GLIBC__)
|
||||
|
||||
static void
|
||||
mem_purge(void) {
|
||||
isc_stdtime_t now = isc_stdtime_now();
|
||||
isc_stdtime_t last = atomic_load_relaxed(&last_purge);
|
||||
|
||||
if (now > last &&
|
||||
atomic_compare_exchange_strong_acq_rel(&last_purge, &last, now))
|
||||
{
|
||||
#if defined(JEMALLOC_API_SUPPORTED)
|
||||
(void)mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".decay",
|
||||
NULL, NULL, NULL, 0);
|
||||
#elif defined(__GLIBC__)
|
||||
(void)malloc_trim(0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
static void
|
||||
mem_purge(void) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* Perform a free, doing memory filling and overrun detection as necessary.
|
||||
*/
|
||||
|
|
@ -407,6 +442,13 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size, int flags) {
|
|||
ADJUST_ZERO_ALLOCATION_SIZE(size);
|
||||
|
||||
sdallocx(mem, size, flags | ctx->jemalloc_flags);
|
||||
|
||||
freed_bytes += size;
|
||||
|
||||
if (freed_bytes >= purge_threshold) {
|
||||
freed_bytes = 0;
|
||||
mem_purge();
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
|
|
@ -465,6 +507,22 @@ isc__mem_initialize(void) {
|
|||
*/
|
||||
#ifdef JEMALLOC_API_SUPPORTED
|
||||
RUNTIME_CHECK(ISC__MEM_ZERO == MALLOCX_ZERO);
|
||||
|
||||
/*
|
||||
* ignore errors — volumetric-based purge in mem_put handles the rest
|
||||
* regardless
|
||||
*/
|
||||
|
||||
(void)mallctl("background_thread", NULL, NULL, &(bool){ true },
|
||||
sizeof(bool));
|
||||
|
||||
(void)mallctl("arenas.dirty_decay_ms", NULL, NULL,
|
||||
&default_dirty_decay_ms, sizeof(default_dirty_decay_ms));
|
||||
|
||||
(void)mallctl("arena." STRINGIFY(MALLCTL_ARENAS_ALL) ".dirty_decay_ms",
|
||||
NULL, NULL, &default_dirty_decay_ms,
|
||||
sizeof(default_dirty_decay_ms));
|
||||
|
||||
#endif /* JEMALLOC_API_SUPPORTED */
|
||||
|
||||
isc_mutex_init(&contextslock);
|
||||
|
|
@ -804,7 +862,7 @@ isc__mem_reget(isc_mem_t *ctx, void *old_ptr, size_t old_size, size_t new_size,
|
|||
|
||||
ADJUST_ZERO_ALLOCATION_SIZE(new_size);
|
||||
|
||||
#ifdef HAVE_JEMALLOC
|
||||
#ifdef JEMALLOC_API_SUPPORTED
|
||||
new_ptr = mem_realloc(ctx, old_ptr, new_size, flags);
|
||||
#else
|
||||
new_ptr = mem_realloc(ctx, old_ptr, new_size,
|
||||
|
|
|
|||
Loading…
Reference in a new issue