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

Move SIEVE-LRU to dns_slabtop_t structure

As the qpcache has only one active header at the time, we can move the
SIEVE-LRU members from dns_slabheader_t to dns_slabtop_t structure thus
saving a little bit of memory in each slabheader and using it only once
per type.
This commit is contained in:
Ondřej Surý 2025-08-13 09:30:45 +02:00
parent f4d8841f0d
commit d7801aec71
No known key found for this signature in database
GPG Key ID: 2820F37E873DEA41
5 changed files with 76 additions and 53 deletions

View File

@ -69,6 +69,11 @@ struct dns_slabtop {
dns_slabtop_t *next;
dns_slabheader_t *header;
dns_typepair_t typepair;
/*% Used for SIEVE-LRU (cache) and changed_list (zone) */
ISC_LINK(struct dns_slabtop) link;
/*% Used for SIEVE-LRU */
bool visited;
};
struct dns_slabheader {
@ -132,11 +137,6 @@ struct dns_slabheader {
dns_gluelist_t *gluelist;
/*% Used for SIEVE-LRU (cache) and changed_list (zone) */
ISC_LINK(struct dns_slabheader) link;
/*% Used for SIEVE-LRU */
bool visited;
/*%
* Case vector. If the bit is set then the corresponding
* character in the owner name needs to be AND'd with 0x20,

View File

@ -154,23 +154,22 @@ typedef uint8_t dns_secproto_t;
typedef struct dns_signature dns_signature_t;
typedef struct dns_skr dns_skr_t;
typedef struct dns_slabheader dns_slabheader_t;
typedef ISC_LIST(dns_slabheader_t) dns_slabheaderlist_t;
typedef struct dns_ssurule dns_ssurule_t;
typedef struct dns_ssutable dns_ssutable_t;
typedef struct dns_stats dns_stats_t;
typedef uint32_t dns_rdatastatstype_t;
typedef struct dns_tkeyctx dns_tkeyctx_t;
typedef struct dns_transport dns_transport_t;
typedef struct dns_transport_list dns_transport_list_t;
typedef uint16_t dns_trust_t;
typedef struct dns_tsigkeyring dns_tsigkeyring_t;
typedef struct dns_tsigkey dns_tsigkey_t;
typedef uint32_t dns_ttl_t;
typedef uint32_t dns_typepair_t;
typedef struct dns_unreachcache dns_unreachcache_t;
typedef struct dns_update_state dns_update_state_t;
typedef struct dns_validator dns_validator_t;
typedef struct dns_view dns_view_t;
typedef struct dns_ssurule dns_ssurule_t;
typedef struct dns_ssutable dns_ssutable_t;
typedef struct dns_stats dns_stats_t;
typedef uint32_t dns_rdatastatstype_t;
typedef struct dns_tkeyctx dns_tkeyctx_t;
typedef struct dns_transport dns_transport_t;
typedef struct dns_transport_list dns_transport_list_t;
typedef uint16_t dns_trust_t;
typedef struct dns_tsigkeyring dns_tsigkeyring_t;
typedef struct dns_tsigkey dns_tsigkey_t;
typedef uint32_t dns_ttl_t;
typedef uint32_t dns_typepair_t;
typedef struct dns_unreachcache dns_unreachcache_t;
typedef struct dns_update_state dns_update_state_t;
typedef struct dns_validator dns_validator_t;
typedef struct dns_view dns_view_t;
typedef ISC_LIST(dns_view_t) dns_viewlist_t;
typedef struct dns_zone dns_zone_t;
typedef ISC_LIST(dns_zone_t) dns_zonelist_t;

View File

@ -201,13 +201,13 @@ typedef struct qpcache_bucket {
isc_heap_t *heap;
/* SIEVE-LRU cache cleaning state. */
ISC_SIEVE(dns_slabheader_t) sieve;
ISC_SIEVE(dns_slabtop_t) sieve;
/* Padding to prevent false sharing between locks. */
uint8_t __padding[ISC_OS_CACHELINE_SIZE -
(sizeof(isc_queue_t) + sizeof(isc_rwlock_t) +
sizeof(isc_heap_t *) +
sizeof(ISC_SIEVE(dns_slabheader_t))) %
sizeof(ISC_SIEVE(dns_slabtop_t))) %
ISC_OS_CACHELINE_SIZE];
} qpcache_bucket_t;
@ -486,13 +486,15 @@ expire_lru_headers(qpcache_t *qpdb, uint32_t idx, size_t requested,
size_t expired = 0;
do {
dns_slabheader_t *header =
ISC_SIEVE_NEXT(qpdb->buckets[idx].sieve, visited, link);
if (header == NULL) {
dns_slabtop_t *top = ISC_SIEVE_NEXT(qpdb->buckets[idx].sieve,
visited, link);
if (top == NULL) {
return;
}
ISC_SIEVE_UNLINK(qpdb->buckets[idx].sieve, header, link);
ISC_SIEVE_UNLINK(qpdb->buckets[idx].sieve, top, link);
dns_slabheader_t *header = top->header;
expired += rdataset_size(header);
@ -529,7 +531,7 @@ qpcache_miss(qpcache_t *qpdb, dns_slabheader_t *newheader,
tlocktypep DNS__DB_FLARG_PASS);
}
ISC_SIEVE_INSERT(qpdb->buckets[idx].sieve, newheader, link);
ISC_SIEVE_INSERT(qpdb->buckets[idx].sieve, newheader->top, link);
}
static void
@ -537,7 +539,7 @@ qpcache_hit(qpcache_t *qpdb ISC_ATTR_UNUSED, dns_slabheader_t *header) {
/*
* On cache hit, we only mark the header as seen.
*/
ISC_SIEVE_MARK(header, visited);
ISC_SIEVE_MARK(header->top, visited);
}
/*
@ -586,6 +588,12 @@ clean_cache_node(qpcache_t *qpdb, qpcnode_t *node) {
} else {
node->data = top->next;
}
if (ISC_LINK_LINKED(top, link)) {
ISC_SIEVE_UNLINK(
qpdb->buckets[node->locknum].sieve, top,
link);
}
dns_slabtop_destroy(((dns_db_t *)qpdb)->mctx, &top);
} else {
top_prev = top;
@ -2804,13 +2812,16 @@ find_header:
return DNS_R_UNCHANGED;
}
qpcache_miss(qpdb, newheader, &nlocktype,
&tlocktype DNS__DB_FLARG_PASS);
top->header = newheader;
newheader->top = top;
newheader->down = header;
ISC_SIEVE_UNLINK(qpdb->buckets[qpnode->locknum].sieve, top,
link);
qpcache_miss(qpdb, newheader, &nlocktype,
&tlocktype DNS__DB_FLARG_PASS);
mark_ancient(header);
if (sigheader != NULL) {
mark_ancient(sigheader);
@ -2827,12 +2838,12 @@ find_header:
dns_slabtop_t *newtop = dns_slabtop_new(
((dns_db_t *)qpdb)->mctx, newheader->typepair);
qpcache_miss(qpdb, newheader, &nlocktype,
&tlocktype DNS__DB_FLARG_PASS);
newtop->header = newheader;
newheader->top = newtop;
qpcache_miss(qpdb, newheader, &nlocktype,
&tlocktype DNS__DB_FLARG_PASS);
if (prio_header(newtop)) {
/* This is a priority type, prepend it */
newtop->next = qpnode->data;
@ -3755,7 +3766,6 @@ static void
qpcnode_deletedata(dns_dbnode_t *node ISC_ATTR_UNUSED, void *data) {
dns_slabheader_t *header = data;
qpcache_t *qpdb = HEADERNODE(header)->qpdb;
int idx = HEADERNODE(header)->locknum;
if (header->heap != NULL && header->heap_index != 0) {
isc_heap_delete(header->heap, header->heap_index);
@ -3767,10 +3777,6 @@ qpcnode_deletedata(dns_dbnode_t *node ISC_ATTR_UNUSED, void *data) {
update_rrsetstats(qpdb->rrsetstats, header->typepair,
atomic_load_acquire(&header->attributes), false);
if (ISC_LINK_LINKED(header, link)) {
ISC_SIEVE_UNLINK(qpdb->buckets[idx].sieve, header, link);
}
if (header->noqname != NULL) {
dns_slabheader_freeproof(qpdb->common.mctx, &header->noqname);
}
@ -3855,7 +3861,7 @@ static dns_dbmethods_t qpdb_cachemethods = {
static void
qpcnode_destroy(qpcnode_t *qpnode) {
dns_slabtop_t *top = NULL, *top_next = NULL;
dns_db_t *db = (dns_db_t *)qpnode->qpdb;
qpcache_t *qpdb = qpnode->qpdb;
for (top = qpnode->data; top != NULL; top = top_next) {
top_next = top->next;
@ -3867,7 +3873,11 @@ qpcnode_destroy(qpcnode_t *qpnode) {
}
top->header = NULL;
dns_slabtop_destroy(db->mctx, &top);
if (ISC_LINK_LINKED(top, link)) {
ISC_SIEVE_UNLINK(qpdb->buckets[qpnode->locknum].sieve,
top, link);
}
dns_slabtop_destroy(((dns_db_t *)qpdb)->mctx, &top);
}
dns_name_free(&qpnode->name, qpnode->mctx);

View File

@ -113,6 +113,13 @@ typedef struct qpz_changed {
typedef ISC_LIST(qpz_changed_t) qpz_changedlist_t;
typedef struct qpz_resigned {
dns_slabheader_t *header;
ISC_LINK(struct qpz_resigned) link;
} qpz_resigned_t;
typedef ISC_LIST(qpz_resigned_t) qpz_resignedlist_t;
typedef struct qpz_version qpz_version_t;
struct qpz_version {
/* Not locked */
@ -122,7 +129,7 @@ struct qpz_version {
/* Locked by database lock. */
bool writer;
qpz_changedlist_t changed_list;
dns_slabheaderlist_t resigned_list;
qpz_resignedlist_t resigned_list;
ISC_LINK(qpz_version_t) link;
bool secure;
bool havensec3;
@ -1284,7 +1291,6 @@ newversion(dns_db_t *db, dns_dbversion_t **versionp) {
static void
resigninsert(dns_slabheader_t *newheader) {
REQUIRE(newheader->heap_index == 0);
REQUIRE(!ISC_LINK_LINKED(newheader, link));
LOCK(get_heap_lock(newheader));
isc_heap_insert(HEADERNODE(newheader)->heap->heap, newheader);
@ -1304,7 +1310,15 @@ resigndelete(qpzonedb_t *qpdb ISC_ATTR_UNUSED, qpz_version_t *version,
header->heap_index = 0;
qpznode_acquire(qpdb, HEADERNODE(header) DNS__DB_FLARG_PASS);
ISC_LIST_APPEND(version->resigned_list, header, link);
qpz_resigned_t *resigned = isc_mem_get(((dns_db_t *)qpdb)->mctx,
sizeof(*resigned));
*resigned = (qpz_resigned_t){
.header = header,
.link = ISC_LINK_INITIALIZER,
};
ISC_LIST_APPEND(version->resigned_list, resigned, link);
}
static void
@ -1358,7 +1372,7 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
qpznode_t *node = NULL;
bool rollback = false;
qpz_changedlist_t cleanup_list;
dns_slabheaderlist_t resigned_list;
qpz_resignedlist_t resigned_list;
uint32_t serial, least_serial;
REQUIRE(VALID_QPZONE(qpdb));
@ -1532,11 +1546,14 @@ closeversion(dns_db_t *db, dns_dbversion_t **versionp,
/*
* Commit/rollback re-signed headers.
*/
ISC_LIST_FOREACH (resigned_list, header, link) {
ISC_LIST_FOREACH (resigned_list, resigned, link) {
isc_rwlock_t *nlock = NULL;
isc_rwlocktype_t nlocktype = isc_rwlocktype_none;
dns_slabheader_t *header = resigned->header;
ISC_LIST_UNLINK(resigned_list, header, link);
ISC_LIST_UNLINK(resigned_list, resigned, link);
isc_mem_put(db->mctx, resigned, sizeof(*resigned));
nlock = qpzone_get_lock(HEADERNODE(header));
NODE_WRLOCK(nlock, &nlocktype);

View File

@ -346,7 +346,6 @@ dns_rdataslab_fromrdataset(dns_rdataset_t *rdataset, isc_mem_t *mctx,
.typepair = typepair,
.trust = rdataset->trust,
.ttl = rdataset->ttl,
.link = ISC_LINK_INITIALIZER,
};
}
@ -858,11 +857,9 @@ dns_slabheader_copycase(dns_slabheader_t *dest, dns_slabheader_t *src) {
void
dns_slabheader_reset(dns_slabheader_t *h, dns_dbnode_t *node) {
ISC_LINK_INIT(h, link);
h->heap_index = 0;
h->heap = NULL;
h->node = node;
h->visited = false;
atomic_init(&h->attributes, 0);
atomic_init(&h->last_refresh_fail_ts, 0);
@ -878,7 +875,6 @@ dns_slabheader_new(isc_mem_t *mctx, dns_dbnode_t *node) {
h = isc_mem_get(mctx, sizeof(*h));
*h = (dns_slabheader_t){
.link = ISC_LINK_INITIALIZER,
.node = node,
};
return h;
@ -1246,6 +1242,7 @@ dns_slabtop_new(isc_mem_t *mctx, dns_typepair_t typepair) {
dns_slabtop_t *top = isc_mem_get(mctx, sizeof(*top));
*top = (dns_slabtop_t){
.typepair = typepair,
.link = ISC_LINK_INITIALIZER,
};
return top;