From: Yorgos Thessalonikefs Date: Tue, 29 Apr 2025 13:21:47 +0000 (+0200) Subject: Auto-configure '-slabs' values (#1276) X-Git-Tag: release-1.24.0rc1~103 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fcc21885e49f3f3bd0645aec2603abd714165f9a;p=thirdparty%2Funbound.git Auto-configure '-slabs' values (#1276) - Auto-configure '-slabs' values to a power of 2 value close to num-threads by default for multi-threaded environments. Co-authored-by: Wouter Wijngaards --- diff --git a/doc/unbound.conf.5.in b/doc/unbound.conf.5.in index 4c7ea9f75..e963a3e3a 100644 --- a/doc/unbound.conf.5.in +++ b/doc/unbound.conf.5.in @@ -259,9 +259,12 @@ A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes or gigabytes (1024*1024 bytes in a megabyte). .TP .B msg\-cache\-slabs: \fI -Number of slabs in the message cache. Slabs reduce lock contention by threads. -Must be set to a power of 2. Setting (close) to the number of cpus is a -reasonable guess. +Number of slabs in the message cache. +Slabs reduce lock contention by threads. +Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .TP .B num\-queries\-per\-thread: \fI The number of queries that every thread will service simultaneously. @@ -400,8 +403,12 @@ A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes or gigabytes (1024*1024 bytes in a megabyte). .TP .B rrset\-cache\-slabs: \fI -Number of slabs in the RRset cache. Slabs reduce lock contention by threads. +Number of slabs in the RRset cache. +Slabs reduce lock contention by threads. Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .TP .B cache\-max\-ttl: \fI Time to live maximum for RRsets and messages in the cache. Default is @@ -436,8 +443,12 @@ Time to live for entries in the host cache. The host cache contains roundtrip timing, lameness and EDNS support information. Default is 900. .TP .B infra\-cache\-slabs: \fI -Number of slabs in the infrastructure cache. Slabs reduce lock contention -by threads. Must be set to a power of 2. +Number of slabs in the infrastructure cache. +Slabs reduce lock contention by threads. +Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .TP .B infra\-cache\-numhosts: \fI Number of hosts for which information is cached. Default is 10000. @@ -1494,9 +1505,12 @@ A plain number is in bytes, append 'k', 'm' or 'g' for kilobytes, megabytes or gigabytes (1024*1024 bytes in a megabyte). .TP .B key\-cache\-slabs: \fI -Number of slabs in the key cache. Slabs reduce lock contention by threads. -Must be set to a power of 2. Setting (close) to the number of cpus is a -reasonable guess. +Number of slabs in the key cache. +Slabs reduce lock contention by threads. +Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .TP .B neg\-cache\-size: \fI Number of bytes size of the aggressive negative cache. Default is 1 megabyte. @@ -1903,9 +1917,12 @@ The ratelimit structure is small, so this data structure likely does not need to be large. .TP 5 .B ratelimit\-slabs: \fI -Give power of 2 number of slabs, this is used to reduce lock contention -in the ratelimit tracking data structure. Close to the number of cpus is -a fairly good setting. +Number of slabs in the ratelimit tracking data structure. +Slabs reduce lock contention by threads. +Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .TP 5 .B ratelimit\-factor: \fI Set the amount of queries to rate limit when the limit is exceeded. @@ -1974,9 +1991,12 @@ The ip ratelimit structure is small, so this data structure likely does not need to be large. .TP 5 .B ip\-ratelimit\-slabs: \fI -Give power of 2 number of slabs, this is used to reduce lock contention -in the ip ratelimit tracking data structure. Close to the number of cpus is -a fairly good setting. +Number of slabs in the ip ratelimit tracking data structure. +Slabs reduce lock contention by threads. +Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .TP 5 .B ip\-ratelimit\-factor: \fI Set the amount of queries to rate limit when the limit is exceeded. @@ -2610,9 +2630,12 @@ The shared secret cache is used when a same client is making multiple queries using the same public key. It saves a substantial amount of CPU. .TP .B dnscrypt\-shared\-secret\-cache\-slabs: \fI -Give power of 2 number of slabs, this is used to reduce lock contention -in the dnscrypt shared secrets cache. Close to the number of cpus is -a fairly good setting. +Number of slabs in the dnscrypt shared secrets cache. +Slabs reduce lock contention by threads. +Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .TP .B dnscrypt\-nonce\-cache\-size: \fI Give the size of the data structure in which the client nonces are kept in. @@ -2621,9 +2644,12 @@ The nonce cache is used to prevent dnscrypt message replaying. Client nonce should be unique for any pair of client pk/server sk. .TP .B dnscrypt\-nonce\-cache\-slabs: \fI -Give power of 2 number of slabs, this is used to reduce lock contention -in the dnscrypt nonce cache. Close to the number of cpus is -a fairly good setting. +Number of slabs in the dnscrypt nonce cache. +Slabs reduce lock contention by threads. +Must be set to a power of 2. +Setting (close) to the number of cpus is a fairly good setting. +If left unconfigured, it will be configured automatically to be a power of 2 +close to the number of configured threads in multi-threaded environments. .SS "EDNS Client Subnet Module Options" .LP The ECS module must be configured in the \fBmodule\-config:\fR directive e.g., diff --git a/testcode/unitauth.c b/testcode/unitauth.c index 23c57e095..401e93af3 100644 --- a/testcode/unitauth.c +++ b/testcode/unitauth.c @@ -670,6 +670,7 @@ authtest_addzone(struct auth_zones* az, const char* name, char* fname) auth_zone_set_zonefile(z, fname); z->for_upstream = 1; cfg = config_create(); + config_auto_slab_values(cfg); free(cfg->chrootdir); cfg->chrootdir = NULL; diff --git a/testcode/unitinfra.c b/testcode/unitinfra.c index 6834c51ee..91a88f6ae 100644 --- a/testcode/unitinfra.c +++ b/testcode/unitinfra.c @@ -131,6 +131,7 @@ void infra_test(void) unit_show_feature("infra cache"); unit_assert(ipstrtoaddr("127.0.0.1", 53, &one, &onelen)); + config_auto_slab_values(cfg); slab = infra_create(cfg); /* insert new record */ unit_assert( infra_host(slab, &one, onelen, zone, zonelen, now, diff --git a/testcode/unitzonemd.c b/testcode/unitzonemd.c index 63dc13eda..0420b0361 100644 --- a/testcode/unitzonemd.c +++ b/testcode/unitzonemd.c @@ -267,6 +267,7 @@ static void zonemd_verify_test(char* zname, char* zfile, char* tastr, env.cfg = config_create(); if(!env.cfg) fatal_exit("out of memory"); + config_auto_slab_values(env.cfg); env.now = &now; env.cfg->val_date_override = cfg_convert_timeval(date_override); if(!env.cfg->val_date_override) diff --git a/util/config_file.c b/util/config_file.c index 7566d690c..f1a26674e 100644 --- a/util/config_file.c +++ b/util/config_file.c @@ -169,10 +169,10 @@ config_create(void) cfg->edns_buffer_size = 1232; /* from DNS flagday recommendation */ cfg->msg_buffer_size = 65552; /* 64 k + a small margin */ cfg->msg_cache_size = 4 * 1024 * 1024; - cfg->msg_cache_slabs = 4; + cfg->msg_cache_slabs = 0; cfg->jostle_time = 200; cfg->rrset_cache_size = 4 * 1024 * 1024; - cfg->rrset_cache_slabs = 4; + cfg->rrset_cache_slabs = 0; cfg->host_ttl = 900; cfg->bogus_ttl = 60; cfg->min_ttl = 0; @@ -182,7 +182,7 @@ config_create(void) cfg->prefetch = 0; cfg->prefetch_key = 0; cfg->deny_any = 0; - cfg->infra_cache_slabs = 4; + cfg->infra_cache_slabs = 0; cfg->infra_cache_numhosts = 10000; cfg->infra_cache_min_rtt = 50; cfg->infra_cache_max_rtt = 120000; @@ -291,7 +291,7 @@ config_create(void) cfg->keep_missing = 366*24*3600; /* one year plus a little leeway */ cfg->permit_small_holddown = 0; cfg->key_cache_size = 4 * 1024 * 1024; - cfg->key_cache_slabs = 4; + cfg->key_cache_slabs = 0; cfg->neg_cache_size = 1 * 1024 * 1024; cfg->local_zones = NULL; cfg->local_zones_nodefault = NULL; @@ -341,8 +341,8 @@ config_create(void) cfg->ip_ratelimit_cookie = 0; cfg->ip_ratelimit = 0; cfg->ratelimit = 0; - cfg->ip_ratelimit_slabs = 4; - cfg->ratelimit_slabs = 4; + cfg->ip_ratelimit_slabs = 0; + cfg->ratelimit_slabs = 0; cfg->ip_ratelimit_size = 4*1024*1024; cfg->ratelimit_size = 4*1024*1024; cfg->ratelimit_for_domain = NULL; @@ -367,9 +367,9 @@ config_create(void) cfg->dnscrypt_provider_cert_rotated = NULL; cfg->dnscrypt_secret_key = NULL; cfg->dnscrypt_shared_secret_cache_size = 4*1024*1024; - cfg->dnscrypt_shared_secret_cache_slabs = 4; + cfg->dnscrypt_shared_secret_cache_slabs = 0; cfg->dnscrypt_nonce_cache_size = 4*1024*1024; - cfg->dnscrypt_nonce_cache_slabs = 4; + cfg->dnscrypt_nonce_cache_slabs = 0; cfg->pad_responses = 1; cfg->pad_responses_block_size = 468; /* from RFC8467 */ cfg->pad_queries = 1; @@ -454,6 +454,11 @@ struct config_file* config_create_forlib(void) cfg->val_log_squelch = 1; cfg->minimal_responses = 0; cfg->harden_short_bufsize = 1; + /* Need to explicitly define the slabs from their 0 default value */ + cfg->ip_ratelimit_slabs = 1; + cfg->ratelimit_slabs = 1; + cfg->dnscrypt_shared_secret_cache_slabs = 1; + cfg->dnscrypt_nonce_cache_slabs = 1; return cfg; } @@ -1448,6 +1453,41 @@ create_cfg_parser(struct config_file* cfg, char* filename, const char* chroot) init_cfg_parse(); } +void +config_auto_slab_values(struct config_file* cfg) +{ +#define SET_AUTO_SLAB(var, name, val) \ +do { \ + if(cfg->var == 0) { \ + cfg->var = val; \ + verbose(VERB_QUERY, "setting "name": %lu", (unsigned long)val); \ + } \ +} while(0); +#ifdef THREADS_DISABLED + size_t pow_2_threads = 1; +#else + size_t pow_2_threads = 4; /* pow2 start */ + while (pow_2_threads < (size_t)(cfg->num_threads?cfg->num_threads:1) && + /* 1/3 of the distance to the next pow2 value stays with the + * lower value */ + (size_t)cfg->num_threads > pow_2_threads + (pow_2_threads - 1)/3) { + pow_2_threads <<= 1; + } + log_assert((pow_2_threads & (pow_2_threads - 1)) == 0); /* powerof2? */ +#endif /* THREADS_DISABLED */ + + SET_AUTO_SLAB(msg_cache_slabs, "msg-cache-slabs", pow_2_threads); + SET_AUTO_SLAB(rrset_cache_slabs, "rrset-cache-slabs", pow_2_threads); + SET_AUTO_SLAB(infra_cache_slabs, "infra-cache-slabs", pow_2_threads); + SET_AUTO_SLAB(key_cache_slabs, "key-cache-slabs", pow_2_threads); + SET_AUTO_SLAB(ip_ratelimit_slabs, "ip-ratelimit-slabs", pow_2_threads); + SET_AUTO_SLAB(ratelimit_slabs, "ratelimit-slabs", pow_2_threads); + SET_AUTO_SLAB(dnscrypt_shared_secret_cache_slabs, + "dnscrypt-shared-secret-cache-slabs", pow_2_threads); + SET_AUTO_SLAB(dnscrypt_nonce_cache_slabs, + "dnscrypt-nonce-cache-slabs", pow_2_threads); +} + int config_read(struct config_file* cfg, const char* filename, const char* chroot) { @@ -1512,6 +1552,7 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot) } } globfree(&g); + config_auto_slab_values(cfg); return 1; } #endif /* HAVE_GLOB */ @@ -1535,6 +1576,7 @@ config_read(struct config_file* cfg, const char* filename, const char* chroot) return 0; } + config_auto_slab_values(cfg); return 1; } diff --git a/util/config_file.h b/util/config_file.h index 89bbc1c7d..44ac036b8 100644 --- a/util/config_file.h +++ b/util/config_file.h @@ -966,6 +966,17 @@ struct config_file* config_create(void); */ struct config_file* config_create_forlib(void); +/** + * If _slabs values are not explicitly configured, 0 value, put them in a + * pow2 value close to the number of threads used. + * Starts at the current default 4. + * If num_threads is in between two pow2 values, 1/3 of the way stays with + * the lower pow2 value. + * Exported for unit testing. + * @param config: where the _slabs values reside. + */ +void config_auto_slab_values(struct config_file* config); + /** * Read the config file from the specified filename. * @param config: where options are stored into, must be freshly created.