From 2a9914f8f3b1f0be29a45a0506307d91bc3dfacd Mon Sep 17 00:00:00 2001
From: Libor Peltan <libor.peltan@nic.cz>
Date: Thu, 22 Aug 2024 14:45:31 +0200
Subject: [PATCH] libknot/performance: avoid repeated knot_rdataset_at() inside
 knot_rrset_to_wire_extra()

---
 src/libknot/packet/rrset-wire.c | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/src/libknot/packet/rrset-wire.c b/src/libknot/packet/rrset-wire.c
index a100364565..1d4f78e48e 100644
--- a/src/libknot/packet/rrset-wire.c
+++ b/src/libknot/packet/rrset-wire.c
@@ -323,11 +323,11 @@ static int write_owner(const knot_rrset_t *rrset, uint8_t **dst, size_t *dst_ava
 	return KNOT_EOK;
 }
 
-static int write_fixed_header(const knot_rrset_t *rrset, uint16_t rrset_index,
+static int write_fixed_header(const knot_rrset_t *rrset, const knot_rdata_t *rdata,
                               uint8_t **dst, size_t *dst_avail, uint16_t flags)
 {
 	assert(rrset);
-	assert(rrset_index < rrset->rrs.count);
+	assert(rdata);
 	assert(dst && *dst);
 	assert(dst_avail);
 
@@ -338,10 +338,8 @@ static int write_fixed_header(const knot_rrset_t *rrset, uint16_t rrset_index,
 	wire_ctx_write_u16(&write, rrset->rclass);
 
 	if ((flags & KNOT_PF_ORIGTTL) && rrset->type == KNOT_RRTYPE_RRSIG) {
-		const knot_rdata_t *rdata = knot_rdataset_at(&rrset->rrs, rrset_index);
 		wire_ctx_write_u32(&write, knot_rrsig_original_ttl(rdata));
 	} else if ((flags & KNOT_PF_SOAMINTTL) && rrset->type == KNOT_RRTYPE_SOA) {
-		const knot_rdata_t *rdata = knot_rdataset_at(&rrset->rrs, rrset_index);
 		wire_ctx_write_u32(&write, MIN(knot_soa_minimum(rdata), rrset->ttl));
 	} else {
 		wire_ctx_write_u32(&write, rrset->ttl);
@@ -432,15 +430,15 @@ static int rdata_traverse_write(const uint8_t **src, size_t *src_avail,
 }
 
 static int write_rdata(const knot_rrset_t *rrset, uint16_t rrset_index,
-                       uint8_t **dst, size_t *dst_avail, knot_compr_t *compr)
+                       const knot_rdata_t *rdata, uint8_t **dst, size_t *dst_avail,
+                       knot_compr_t *compr)
 {
 	assert(rrset);
 	assert(rrset_index < rrset->rrs.count);
+	assert(rdata);
 	assert(dst && *dst);
 	assert(dst_avail);
 
-	const knot_rdata_t *rdata = knot_rdataset_at(&rrset->rrs, rrset_index);
-
 	// Reserve space for RDLENGTH.
 	if (sizeof(uint16_t) > *dst_avail) {
 		return KNOT_ESPACE;
@@ -477,7 +475,8 @@ static int write_rdata(const knot_rrset_t *rrset, uint16_t rrset_index,
 	return KNOT_EOK;
 }
 
-static int write_rr(const knot_rrset_t *rrset, uint16_t rrset_index, uint8_t **dst,
+static int write_rr(const knot_rrset_t *rrset, uint16_t rrset_index,
+                    const knot_rdata_t *rdata, uint8_t **dst,
                     size_t *dst_avail, knot_compr_t *compr, uint16_t flags)
 {
 	int ret = write_owner(rrset, dst, dst_avail, compr);
@@ -485,12 +484,12 @@ static int write_rr(const knot_rrset_t *rrset, uint16_t rrset_index, uint8_t **d
 		return ret;
 	}
 
-	ret = write_fixed_header(rrset, rrset_index, dst, dst_avail, flags);
+	ret = write_fixed_header(rrset, rdata, dst, dst_avail, flags);
 	if (ret != KNOT_EOK) {
 		return ret;
 	}
 
-	return write_rdata(rrset, rrset_index, dst, dst_avail, compr);
+	return write_rdata(rrset, rrset_index, rdata, dst, dst_avail, compr);
 }
 
 _public_
@@ -512,9 +511,11 @@ int knot_rrset_to_wire_extra(const knot_rrset_t *rrset, uint8_t *wire,
 	size_t capacity = max_size;
 
 	uint16_t count = rrset->rrs.count;
+	knot_rdata_t *rdata = rotate > 1 ? knot_rdataset_at(&rrset->rrs, rotate - 1) : rrset->rrs.rdata;
 	for (int i = rotate; i < count + rotate; i++) {
 		uint16_t pos = (i < count) ? i : (i - count);
-		int ret = write_rr(rrset, pos, &write, &capacity, compr, flags);
+		rdata = pos ? knot_rdataset_next(rdata) : rrset->rrs.rdata;
+		int ret = write_rr(rrset, pos, rdata, &write, &capacity, compr, flags);
 		if (ret != KNOT_EOK) {
 			return ret;
 		}
-- 
GitLab