2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-30 22:15:20 +00:00

Switch symtab to use fxhash hashing

This merge request resolves some performance regressions introduced
with the change from isc_symtab_t to isc_hashmap_t.

The key improvements are:

1. Using a faster hash function than both isc_hashmap_t and
   isc_symtab_t. The previous implementation used SipHash, but the
   hashflood resistance properties of SipHash are unneeded for config
   parsing.
2. Shrinking the initial size of the isc_hashmap_t used inside
   isc_symtab_t. Symtab is mainly used for config parsing, and the
   when used that way it will have between 1 and ~50 keys, but the
   previous implementation initialized a map with 128 slots.
   By initializing a smaller map, we speed up mallocs and optimize for
   the typical case of few config keys.
3. Slight optimization of the string matching in the hashmap, so that
   the tail is handled in a single load + comparison, instead of byte
   by byte.
   Of the three improvements, this is the least important.
This commit is contained in:
alessio
2025-02-27 07:37:04 +01:00
parent d2214cb704
commit e1e10adc3a
4 changed files with 118 additions and 20 deletions

View File

@@ -16,6 +16,7 @@
#include <stdbool.h>
#include <isc/ascii.h>
#include <isc/fxhash.h>
#include <isc/hash.h>
#include <isc/hashmap.h>
#include <isc/magic.h>
@@ -31,9 +32,9 @@ typedef struct elt {
isc_symvalue_t value;
} elt_t;
/* 7 bits means 128 entries at creation, which matches the common use of
/* 4 bits means 16 entries at creation, which matches the common use of
* symtab */
#define ISC_SYMTAB_INIT_HASH_BITS 7
#define ISC_SYMTAB_INIT_HASH_BITS 4
#define SYMTAB_MAGIC ISC_MAGIC('S', 'y', 'm', 'T')
#define VALID_SYMTAB(st) ISC_MAGIC_VALID(st, SYMTAB_MAGIC)
@@ -122,7 +123,7 @@ elt__match(void *node, const void *key0, bool case_sensitive) {
if (case_sensitive) {
return memcmp(elt->key, key->key, key->size) == 0;
} else {
return isc_ascii_lowercmp(elt->key, key->key, key->size) == 0;
return isc_ascii_lowerequal(elt->key, key->key, key->size);
}
}
@@ -136,14 +137,11 @@ elt_match_nocase(void *node, const void *key) {
return elt__match(node, key, false);
}
static uint32_t
elt_hash(elt_t *elt, bool case_sensitive) {
isc_hash32_t hash;
isc_hash32_init(&hash);
isc_hash32_hash(&hash, elt->key, elt->size, case_sensitive);
isc_hash32_hash(&hash, &elt->type, sizeof(elt->type), false);
return isc_hash32_finalize(&hash);
static inline uint32_t
elt_hash(elt_t *restrict elt, bool case_sensitive) {
const uint8_t *ptr = elt->key;
size_t len = elt->size;
return fx_hash_bytes(0, ptr, len, case_sensitive);
}
isc_result_t