Skip to content

Commit

Permalink
Integer churn buffer sizing for dnsio_tcp
Browse files Browse the repository at this point in the history
Been through a few rounds of trivial changes here, but some
analyzer or compiler warning always hates it when I use
floating-point sqrt() to come up with an integer answer to feed
malloc, one way or another.  Just give up and implement integer
sqrt instead.
  • Loading branch information
blblack committed Sep 19, 2024
1 parent 63ec15d commit 74903cd
Showing 1 changed file with 36 additions and 2 deletions.
38 changes: 36 additions & 2 deletions src/dnsio_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,41 @@ _Static_assert(_Alignof(pkt_t) <= _Alignof(uint16_t), "No padding for pkt");
struct conn;
typedef struct conn conn_t;

// I keep running into various warnings or analyzer issues with the various
// ways I've cheated with cheap FP-conversion methods to square root a size_t
// and output an unsigned. So we'll just actually provide a proper integer
// square root method to move past all this. It only gets used once to size a
// buffer on thread start, so perf really isn't critical.
//
// This code is more or less copypasta from a stackexchange answer and then
// cleaned up for style and such, but I verified it produces the right answers
// for all the allowed range of values we use it for.
static unsigned sqrt_sizet(size_t input)
{
// This is basically the inverse of CLZ, how many value bits to the right
// of the leading zeros?
size_t shiftme = input;
size_t valbits = 0;
while (shiftme) {
valbits++;
shiftme >>= 1;
}

// Approx starting point
size_t answer = 1LLU << (valbits >> 1);
if (valbits & 1)
answer += answer >> 1;

// Trial divisions to home in
size_t tmp;
do {
tmp = input / answer;
answer = (answer + tmp) >> 1;
} while (answer > tmp);

return answer;
}

// per-thread state
typedef struct {
// These pointers and values are fixed for the life of the thread:
Expand Down Expand Up @@ -1045,8 +1080,7 @@ void* dnsio_tcp_start(void* thread_asvoid)
// Set up the conn_t churn buffer, which saves some per-new-connection
// memory allocation churn by saving up to sqrt(max_clients) old conn_t
// storage for reuse
const double ca = sqrt(thr.max_clients); // avoids a pointless warning
thr.churn_alloc = (unsigned)ca;
thr.churn_alloc = sqrt_sizet(thr.max_clients);
gdnsd_assert(thr.churn_alloc >= 4U); // because tcp_cpt min is 16U
thr.churn = xmalloc_n(thr.churn_alloc, sizeof(*thr.churn));

Expand Down

0 comments on commit 74903cd

Please sign in to comment.