From 1a8d8e0ca519b49d9e5be57e5dd5c774dbacdeca Mon Sep 17 00:00:00 2001 From: Glenn Strauss Date: Thu, 26 Aug 2021 14:49:56 -0400 Subject: [PATCH] [core] periodically malloc_trim() to release mem (fixes #3084) x-ref: "Memory fragmentation with HTTP/2 enabled" https://redmine.lighttpd.net/issues/3084 --- SConstruct | 1 + configure.ac | 1 + src/CMakeLists.txt | 1 + src/config.h.cmake | 1 + src/meson.build | 1 + src/server.c | 24 ++++++++++++++++++++++++ 6 files changed, 29 insertions(+) diff --git a/SConstruct b/SConstruct index 741a8e4f..0b0e64ef 100644 --- a/SConstruct +++ b/SConstruct @@ -429,6 +429,7 @@ if 1: 'localtime_r', 'lstat', 'madvise', + 'malloc_trim', 'mallopt', 'memcpy', 'mempcpy', diff --git a/configure.ac b/configure.ac index ebd2cc8d..a7e07299 100644 --- a/configure.ac +++ b/configure.ac @@ -1500,6 +1500,7 @@ AC_CHECK_FUNCS([\ localtime_r \ lstat \ madvise \ + malloc_trim \ mallopt \ memcpy \ mempcpy \ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7e51e9ca..10c05d68 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -173,6 +173,7 @@ check_function_exists(kqueue HAVE_KQUEUE) check_function_exists(localtime_r HAVE_LOCALTIME_R) check_function_exists(lstat HAVE_LSTAT) check_function_exists(madvise HAVE_MADVISE) +check_function_exists(malloc_trim HAVE_MALLOC_TRIM) check_function_exists(mallopt HAVE_MALLOPT) check_function_exists(memcpy HAVE_MEMCPY) check_function_exists(mempcpy HAVE_MEMPCPY) diff --git a/src/config.h.cmake b/src/config.h.cmake index de9946b7..c59192f3 100644 --- a/src/config.h.cmake +++ b/src/config.h.cmake @@ -127,6 +127,7 @@ #cmakedefine HAVE_LOCALTIME_R #cmakedefine HAVE_LSTAT #cmakedefine HAVE_MADVISE +#cmakedefine HAVE_MALLOC_TRIM #cmakedefine HAVE_MALLOPT #cmakedefine HAVE_MEMCPY #cmakedefine HAVE_MEMPCPY diff --git a/src/meson.build b/src/meson.build index 8b12ef7e..3afc949d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -125,6 +125,7 @@ conf_data.set('HAVE_KQUEUE', compiler.has_function('kqueue', args: defs)) conf_data.set('HAVE_LOCALTIME_R', compiler.has_function('localtime_r', args: defs)) conf_data.set('HAVE_LSTAT', compiler.has_function('lstat', args: defs)) conf_data.set('HAVE_MADVISE', compiler.has_function('madvise', args: defs)) +conf_data.set('HAVE_MALLOC_TRIM', compiler.has_function('malloc_trim', args: defs)) conf_data.set('HAVE_MALLOPT', compiler.has_function('mallopt', args: defs)) conf_data.set('HAVE_MEMCPY', compiler.has_function('memcpy', args: defs)) conf_data.set('HAVE_MEMPCPY', compiler.has_function('mempcpy', args: defs)) diff --git a/src/server.c b/src/server.c index 184890a0..16041148 100644 --- a/src/server.c +++ b/src/server.c @@ -72,6 +72,10 @@ static const buffer default_server_tag = { CONST_STR_LEN(PACKAGE_DESC)+1, 0 }; #endif #endif #include +#if defined(HAVE_MALLOC_TRIM) +static int(*malloc_trim_fn)(size_t); +static size_t malloc_top_pad; +#endif #endif #include "sys-crypto.h" @@ -1872,6 +1876,9 @@ static void server_handle_sigalrm (server * const srv, unix_time64_t mono_ts, un /* clear request and connection pools every 64 secs */ request_pool_free(); connections_pool_clear(srv); + #if defined(HAVE_MALLOC_TRIM) + if (malloc_trim_fn) malloc_trim_fn(malloc_top_pad); + #endif /* attempt to restart dead piped loggers every 64 secs */ if (0 == srv->srvconf.max_worker) fdevent_restart_logger_pipes(mono_ts); @@ -1997,6 +2004,23 @@ int main (int argc, char **argv) { if (mallopt_fn) mallopt_fn(M_ARENA_MAX, 2); /*(ignore error, if any)*/ } #endif + #endif + + #if defined(HAVE_MALLOC_TRIM) + malloc_top_pad = 524288; + { + const char * const top_pad_str = getenv("MALLOC_TOP_PAD_"); + if (top_pad_str) { + unsigned long top_pad = strtoul(top_pad_str, NULL, 10); + if (top_pad != ULONG_MAX) malloc_top_pad = (size_t)top_pad; + } + } + #ifdef LIGHTTPD_STATIC + malloc_trim_fn = malloc_trim; + #else + malloc_trim_fn = + (int (*)(size_t))(intptr_t)dlsym(RTLD_DEFAULT,"malloc_trim"); + #endif #endif /* for nice %b handling in strftime() */