From: Ondřej Surý Date: Mon, 18 Oct 2021 08:15:50 +0000 (+0200) Subject: Use fibonacci hashing for zone counter buckets X-Git-Tag: v9.17.20~37^2~2 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=b01d75be366be6e9f4e0e0995a7a0e2dcf7a7e85;p=thirdparty%2Fbind9.git Use fibonacci hashing for zone counter buckets Change the 'dbuckets' hash table in resolver.c to use fibonacci hashing like the RBT. --- diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index b25d565be61..aef34f843b3 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -197,12 +197,28 @@ #define NS_FAIL_LIMIT 4 #define NS_RR_LIMIT 5 -/* Number of hash buckets for zone counters */ -#ifndef RES_DOMAIN_BUCKETS -#define RES_DOMAIN_BUCKETS 523 -#endif /* ifndef RES_DOMAIN_BUCKETS */ +/* Hash table for zone counters */ +#ifndef RES_DOMAIN_HASH_BITS +#define RES_DOMAIN_HASH_BITS 12 +#endif /* ifndef RES_DOMAIN_HASH_BITS */ #define RES_NOBUCKET 0xffffffff +#define GOLDEN_RATIO_32 0x61C88647 + +#define HASHSIZE(bits) (UINT64_C(1) << (bits)) + +#define RES_DOMAIN_MAX_BITS 32 +#define RES_DOMAIN_OVERCOMMIT 3 + +#define RES_DOMAIN_NEXTTABLE(hindex) ((hindex == 0) ? 1 : 0) + +static inline uint32_t +hash_32(uint32_t val, unsigned int bits) { + REQUIRE(bits <= RES_DOMAIN_MAX_BITS); + /* High bits are more random. */ + return (val * GOLDEN_RATIO_32 >> (32 - bits)); +} + /*% * Maximum EDNS0 input packet size. */ @@ -484,9 +500,8 @@ struct fctxcount { }; typedef struct zonebucket { - isc_mem_t *mctx; - ISC_LIST(fctxcount_t) list; isc_mutex_t lock; + ISC_LIST(fctxcount_t) list; } zonebucket_t; typedef struct alternate { @@ -521,6 +536,7 @@ struct dns_resolver { isc_dscp_t querydscp6; unsigned int nbuckets; fctxbucket_t *buckets; + uint8_t dhashbits; zonebucket_t *dbuckets; uint32_t lame_ttl; ISC_LIST(alternate_t) alternates; @@ -1501,15 +1517,17 @@ fcount_incr(fetchctx_t *fctx, bool force) { isc_result_t result = ISC_R_SUCCESS; zonebucket_t *dbucket = NULL; fctxcount_t *counter = NULL; - unsigned int bucketnum; + uint32_t hashval; + uint32_t dbucketnum; REQUIRE(fctx != NULL); REQUIRE(fctx->res != NULL); INSIST(fctx->dbucketnum == RES_NOBUCKET); - bucketnum = dns_name_fullhash(fctx->domain, false) % RES_DOMAIN_BUCKETS; + hashval = dns_name_fullhash(fctx->domain, false); + dbucketnum = hash_32(hashval, fctx->res->dhashbits); - dbucket = &fctx->res->dbuckets[bucketnum]; + dbucket = &fctx->res->dbuckets[dbucketnum]; LOCK(&dbucket->lock); for (counter = ISC_LIST_HEAD(dbucket->list); counter != NULL; @@ -1521,18 +1539,16 @@ fcount_incr(fetchctx_t *fctx, bool force) { } if (counter == NULL) { - counter = isc_mem_get(dbucket->mctx, sizeof(fctxcount_t)); - { - ISC_LINK_INIT(counter, link); - counter->count = 1; - counter->logged = 0; - counter->allowed = 1; - counter->dropped = 0; - counter->domain = - dns_fixedname_initname(&counter->dfname); - dns_name_copy(fctx->domain, counter->domain); - ISC_LIST_APPEND(dbucket->list, counter, link); - } + counter = isc_mem_get(fctx->res->mctx, sizeof(*counter)); + *counter = (fctxcount_t){ + .count = 1, + .allowed = 1, + }; + + counter->domain = dns_fixedname_initname(&counter->dfname); + ISC_LINK_INIT(counter, link); + dns_name_copy(fctx->domain, counter->domain); + ISC_LIST_APPEND(dbucket->list, counter, link); } else { uint_fast32_t spill = atomic_load_acquire(&fctx->res->zspill); if (!force && spill != 0 && counter->count >= spill) { @@ -1547,7 +1563,7 @@ fcount_incr(fetchctx_t *fctx, bool force) { UNLOCK(&dbucket->lock); if (result == ISC_R_SUCCESS) { - fctx->dbucketnum = bucketnum; + fctx->dbucketnum = dbucketnum; } return (result); @@ -1582,7 +1598,7 @@ fcount_decr(fetchctx_t *fctx) { if (counter->count == 0) { ISC_LIST_UNLINK(dbucket->list, counter, link); - isc_mem_put(dbucket->mctx, counter, sizeof(*counter)); + isc_mem_put(fctx->res->mctx, counter, sizeof(*counter)); } } @@ -9678,13 +9694,12 @@ destroy(dns_resolver_t *res) { } isc_mem_put(res->mctx, res->buckets, res->nbuckets * sizeof(fctxbucket_t)); - for (i = 0; i < RES_DOMAIN_BUCKETS; i++) { + for (i = 0; i < HASHSIZE(res->dhashbits); i++) { INSIST(ISC_LIST_EMPTY(res->dbuckets[i].list)); - isc_mem_detach(&res->dbuckets[i].mctx); isc_mutex_destroy(&res->dbuckets[i].lock); } isc_mem_put(res->mctx, res->dbuckets, - RES_DOMAIN_BUCKETS * sizeof(zonebucket_t)); + HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); if (res->dispatches4 != NULL) { dns_dispatchset_destroy(&res->dispatches4); } @@ -9767,11 +9782,10 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr, unsigned int options, dns_dispatchmgr_t *dispatchmgr, dns_dispatch_t *dispatchv4, dns_dispatch_t *dispatchv6, dns_resolver_t **resp) { - dns_resolver_t *res = NULL; isc_result_t result = ISC_R_SUCCESS; - unsigned int i, buckets_created = 0, dbuckets_created = 0; + char name[sizeof("res4294967295")]; + dns_resolver_t *res = NULL; isc_task_t *task = NULL; - char name[16]; /* * Create a resolver. @@ -9804,6 +9818,7 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, .maxdepth = DEFAULT_RECURSION_DEPTH, .maxqueries = DEFAULT_MAX_QUERIES, .nbuckets = ntasks, + .dhashbits = RES_DOMAIN_HASH_BITS, .querydscp4 = -1, .querydscp6 = -1 }; @@ -9832,7 +9847,7 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, res->buckets = isc_mem_get(view->mctx, ntasks * sizeof(res->buckets[0])); - for (i = 0; i < ntasks; i++) { + for (uint32_t i = 0; i < ntasks; i++) { res->buckets[i] = (fctxbucket_t){ 0 }; isc_mutex_init(&res->buckets[i].lock); @@ -9848,24 +9863,22 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr, goto cleanup_buckets; } - snprintf(name, sizeof(name), "res%u", i); + snprintf(name, sizeof(name), "res%" PRIu32, i); isc_task_setname(res->buckets[i].task, name, res); isc_mem_attach(view->mctx, &res->buckets[i].mctx); ISC_LIST_INIT(res->buckets[i].fctxs); atomic_init(&res->buckets[i].exiting, false); - buckets_created++; } res->dbuckets = isc_mem_get(view->mctx, - RES_DOMAIN_BUCKETS * sizeof(res->dbuckets[0])); - for (i = 0; i < RES_DOMAIN_BUCKETS; i++) { - res->dbuckets[i] = (zonebucket_t){ 0 }; + HASHSIZE(res->dhashbits) * + sizeof(res->dbuckets[0])); + for (size_t i = 0; i < HASHSIZE(res->dhashbits); i++) { + res->dbuckets[i] = (zonebucket_t){ .list = { 0 } }; ISC_LIST_INIT(res->dbuckets[i].list); - isc_mem_attach(view->mctx, &res->dbuckets[i].mctx); isc_mutex_init(&res->dbuckets[i].lock); - dbuckets_created++; } if (dispatchv4 != NULL) { @@ -9912,15 +9925,14 @@ cleanup_primelock: dns_dispatchset_destroy(&res->dispatches4); } - for (i = 0; i < dbuckets_created; i++) { + for (size_t i = 0; i < HASHSIZE(res->dhashbits); i++) { isc_mutex_destroy(&res->dbuckets[i].lock); - isc_mem_detach(&res->dbuckets[i].mctx); } isc_mem_put(view->mctx, res->dbuckets, - RES_DOMAIN_BUCKETS * sizeof(zonebucket_t)); + HASHSIZE(res->dhashbits) * sizeof(zonebucket_t)); cleanup_buckets: - for (i = 0; i < buckets_created; i++) { + for (size_t i = 0; i < ntasks; i++) { isc_mem_detach(&res->buckets[i].mctx); isc_mutex_destroy(&res->buckets[i].lock); isc_task_shutdown(res->buckets[i].task); @@ -11099,7 +11111,7 @@ dns_resolver_dumpfetches(dns_resolver_t *resolver, isc_statsformat_t format, REQUIRE(fp != NULL); REQUIRE(format == isc_statsformat_file); - for (size_t i = 0; i < RES_DOMAIN_BUCKETS; i++) { + for (size_t i = 0; i < HASHSIZE(resolver->dhashbits); i++) { fctxcount_t *fc; LOCK(&resolver->dbuckets[i].lock); for (fc = ISC_LIST_HEAD(resolver->dbuckets[i].list); fc != NULL;