From: Aydın Mercan Date: Mon, 12 Aug 2024 15:17:05 +0000 (+0300) Subject: add a rndc command to toggle jemalloc profiling X-Git-Tag: v9.21.5~26^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b495e9918eaf8f7546d6c51891aa8817b760ffa7;p=thirdparty%2Fbind9.git add a rndc command to toggle jemalloc profiling The new command is `rndc memprof`. The memory profiling status is also reported inside `rndc status`. The status also shows whether named can toggle memory profiling or not and if the server is built with jemalloc. --- diff --git a/bin/named/control.c b/bin/named/control.c index 9d7bc6f1671..4f93d228051 100644 --- a/bin/named/control.c +++ b/bin/named/control.c @@ -233,6 +233,8 @@ named_control_docommand(isccc_sexpr_t *message, bool readonly, command_compare(command, NAMED_COMMAND_SIGN)) { result = named_server_rekey(named_g_server, lex, text); + } else if (command_compare(command, NAMED_COMMAND_MEMPROF)) { + result = named_server_togglememprof(lex); } else if (command_compare(command, NAMED_COMMAND_MKEYS)) { result = named_server_mkeys(named_g_server, lex, text); } else if (command_compare(command, NAMED_COMMAND_NOTIFY)) { diff --git a/bin/named/include/named/control.h b/bin/named/include/named/control.h index cb3c69c8203..79f62e6c10c 100644 --- a/bin/named/include/named/control.h +++ b/bin/named/include/named/control.h @@ -43,6 +43,7 @@ #define NAMED_COMMAND_FREEZE "freeze" #define NAMED_COMMAND_HALT "halt" #define NAMED_COMMAND_LOADKEYS "loadkeys" +#define NAMED_COMMAND_MEMPROF "memprof" #define NAMED_COMMAND_MKEYS "managed-keys" #define NAMED_COMMAND_MODZONE "modzone" #define NAMED_COMMAND_NOTIFY "notify" diff --git a/bin/named/include/named/server.h b/bin/named/include/named/server.h index 90375260b8e..394b55ad4df 100644 --- a/bin/named/include/named/server.h +++ b/bin/named/include/named/server.h @@ -388,3 +388,15 @@ named_server_fetchlimit(named_server_t *server, isc_lex_t *lex, */ isc_result_t named_server_skr(named_server_t *server, isc_lex_t *lex, isc_buffer_t **text); + +/*% + * Toggle memory profiling if supported. + */ +isc_result_t +named_server_togglememprof(isc_lex_t *lex); + +/*% + * Get status of memory profiling. + */ +const char * +named_server_getmemprof(void); diff --git a/bin/named/server.c b/bin/named/server.c index 9eab82568bf..8481cde8ba1 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -140,6 +140,15 @@ #include #endif /* ifdef HAVE_LIBSCF */ +/* On DragonFly BSD the header does not provide jemalloc API */ +#if defined(HAVE_MALLOC_NP_H) && !defined(__DragonFly__) +#include +#define JEMALLOC_API_SUPPORTED 1 +#elif defined(HAVE_JEMALLOC) +#include +#define JEMALLOC_API_SUPPORTED 1 +#endif + #ifdef HAVE_LMDB #include #define configure_newzones configure_newzones_db @@ -358,6 +367,22 @@ typedef struct { isc_result_t result; } ns_dzarg_t; +typedef enum { + MEMPROF_UNSUPPORTED = 0x00, + MEMPROF_INACTIVE = 0x01, + MEMPROF_FAILING = 0x02, + MEMPROF_OFF = 0x03, + MEMPROF_ON = 0x04, +} memprof_status; + +static const char *memprof_status_text[] = { + [MEMPROF_UNSUPPORTED] = "UNSUPPORTED", + [MEMPROF_INACTIVE] = "INACTIVE", + [MEMPROF_FAILING] = "FAILING", + [MEMPROF_OFF] = "OFF", + [MEMPROF_ON] = "ON", +}; + /* * These zones should not leak onto the Internet. */ @@ -10058,6 +10083,39 @@ named_server_closelogswanted(void *arg, int signum) { isc_async_run(named_g_mainloop, named_server_closelogs, server); } +#ifdef JEMALLOC_API_SUPPORTED +static isc_result_t +memprof_toggle(bool active) { + if (mallctl("prof.active", NULL, NULL, &active, sizeof(active)) != 0) { + return ISC_R_FAILURE; + } + + return ISC_R_SUCCESS; +} + +static isc_result_t +memprof_dump(void) { + if (mallctl("prof.dump", NULL, NULL, NULL, 0) != 0) { + return ISC_R_FAILURE; + } + + return ISC_R_SUCCESS; +} +#else +static isc_result_t +memprof_toggle(bool active) { + UNUSED(active); + + return ISC_R_NOTIMPLEMENTED; +} + +static isc_result_t +memprof_dump(void) { + return ISC_R_NOTIMPLEMENTED; +} + +#endif /* JEMALLOC_API_SUPPORTED */ + void named_server_scan_interfaces(named_server_t *server) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, @@ -11930,6 +11988,10 @@ named_server_status(named_server_t *server, isc_buffer_t **text) { : "OFF"); CHECK(putstr(text, line)); + snprintf(line, sizeof(line), "memory profiling is %s\n", + named_server_getmemprof()); + CHECK(putstr(text, line)); + snprintf(line, sizeof(line), "recursive clients: %u/%u/%u\n", isc_quota_getused(&server->sctx->recursionquota), isc_quota_getsoft(&server->sctx->recursionquota), @@ -16140,3 +16202,113 @@ cleanup: return result; } + +isc_result_t +named_server_togglememprof(isc_lex_t *lex) { + isc_result_t result = ISC_R_FAILURE; + bool active; + char *ptr; + + /* Skip the command name. */ + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } + + ptr = next_token(lex, NULL); + if (ptr == NULL) { + return ISC_R_UNEXPECTEDEND; + } else if (!strcasecmp(ptr, "dump")) { + result = memprof_dump(); + if (result != ISC_R_SUCCESS) { + isc_log_write(NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR, + "failed to dump memory profile"); + + } else { + isc_log_write(NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_INFO, + "memory profile dumped"); + } + + goto done; + } else if (!strcasecmp(ptr, "on") || !strcasecmp(ptr, "yes") || + !strcasecmp(ptr, "enable") || !strcasecmp(ptr, "true")) + { + active = true; + } else if (!strcasecmp(ptr, "off") || !strcasecmp(ptr, "no") || + !strcasecmp(ptr, "disable") || !strcasecmp(ptr, "false")) + { + active = false; + } else { + return DNS_R_SYNTAX; + } + + result = memprof_toggle(active); + if (result != ISC_R_SUCCESS) { + isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, + ISC_LOG_ERROR, + "failed to toggle memory profiling"); + } else { + isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, + ISC_LOG_INFO, "memory profiling %s", + active ? "enabled" : "disabled"); + } + +done: + return result; +} + +#ifdef JEMALLOC_API_SUPPORTED +const char * +named_server_getmemprof(void) { + memprof_status status = MEMPROF_ON; + bool is_enabled; + size_t len = sizeof(is_enabled); + + if (mallctl("config.prof", &is_enabled, &len, NULL, 0) != 0) { + status = MEMPROF_FAILING; + goto done; + } + + INSIST(len == sizeof(is_enabled)); + + if (!is_enabled) { + status = MEMPROF_UNSUPPORTED; + goto done; + } + + if (mallctl("opt.prof", &is_enabled, &len, NULL, 0) != 0) { + status = MEMPROF_FAILING; + goto done; + } + + INSIST(len == sizeof(is_enabled)); + + if (!is_enabled) { + status = MEMPROF_INACTIVE; + goto done; + } + + len = sizeof(is_enabled); + if (mallctl("prof.active", &is_enabled, &len, NULL, 0) != 0) { + status = MEMPROF_FAILING; + goto done; + } + + INSIST(len == sizeof(is_enabled)); + + if (!is_enabled) { + status = MEMPROF_OFF; + } + +done: + return memprof_status_text[status]; +} + +#else /* JEMALLOC_API_SUPPORTED */ +const char * +named_server_getmemprof(void) { + return memprof_status_text[MEMPROF_UNSUPPORTED]; +} +#endif /* JEMALLOC_API_SUPPORTED */ diff --git a/bin/rndc/rndc.c b/bin/rndc/rndc.c index 9750d5d5373..38b1caf7755 100644 --- a/bin/rndc/rndc.c +++ b/bin/rndc/rndc.c @@ -143,6 +143,10 @@ command is one of the following:\n\ Display RFC 5011 managed keys information\n\ managed-keys sync [class [view]]\n\ Write RFC 5011 managed keys to disk\n\ + memprof [ on | off | dump ]\n\ + Enable / disable memory profiling or dump the profile.\n\ + Requires named to built with jemalloc and run with the relevant\n\ + MALLOC_CONF environment variables.\n\ modzone zone [class [view]] { zone-options }\n\ Modify a zone's configuration.\n\ Requires allow-new-zones option.\n\ diff --git a/bin/rndc/rndc.rst b/bin/rndc/rndc.rst index 11c35c2d037..80681c84aee 100644 --- a/bin/rndc/rndc.rst +++ b/bin/rndc/rndc.rst @@ -322,6 +322,19 @@ Currently supported commands are: keys in the event of a trust anchor rollover, or as a brute-force repair for key maintenance problems. +.. option:: memprof [(on | off | dump)] + + This command controls memory profiling. To have any effect, :iscman:`named` must be + built with jemalloc, the library have profiling support enabled and run with the + ``prof:true`` allocator configuration. (either via ``MALLOC_CONF`` or ``/etc/malloc.conf``) + + The ``prof_active:false`` option is recommended to ensure the profiling overhead does + not affect :iscman:`named` when not needed. + + The ``on`` and ``off`` options will start and stop the jemalloc memory profiling respectively. + When run with the `dump` option, :iscman:`named` will dump the profile to the working + directory. The name will be chosen automatically by jemalloc. + .. option:: modzone zone [class [view]] configuration This command modifies the configuration of a zone while the server is running. This