]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
clientlog: optimize get_record()
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 4 Jun 2026 14:43:13 +0000 (16:43 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 8 Jun 2026 14:26:21 +0000 (16:26 +0200)
In the clientlog get_record() function use a simplified local version of
UTI_CompareIPs() to be inlined to minimize the overhead of searching in
the slot.

Revert commit 837323d687b9 ("clientlog: simplify code") and unroll the
first assignment in the search for the last hit to help the compiler to
produce faster code.

clientlog.c
test/unit/clientlog.c

index e18f8fced6ef6f9d6d4aefe19ac1a9733795b1f2..a8fd10c61eca5b4ef918dfffcf116e28b3bc6c01 100644 (file)
@@ -214,6 +214,24 @@ compare_total_hits(Record *x, Record *y)
 
 /* ================================================== */
 
+static int
+is_ip_equal(const IPAddr *a, const IPAddr *b)
+{
+  if (a->family != b->family)
+    return 0;
+
+  switch (a->family) {
+    case IPADDR_INET4:
+      return a->addr.in4 == b->addr.in4;
+    case IPADDR_INET6:
+      return memcmp(a->addr.in6, b->addr.in6, sizeof (a->addr.in6)) == 0;
+  }
+
+  return 0;
+}
+
+/* ================================================== */
+
 static Record *
 get_record(IPAddr *ip)
 {
@@ -231,14 +249,15 @@ get_record(IPAddr *ip)
     for (i = 0, oldest_record = NULL; i < SLOT_SIZE; i++) {
       record = ARR_GetElement(records, first + i);
 
-      if (!UTI_CompareIPs(ip, &record->ip_addr, NULL))
+      if (is_ip_equal(ip, &record->ip_addr))
         return record;
 
       if (record->ip_addr.family == IPADDR_UNSPEC)
         break;
 
-      for (j = 0; j < MAX_SERVICES; j++) {
-        if (j == 0 || compare_ts(last_hit, record->last_hit[j]) < 0)
+      last_hit = record->last_hit[0];
+      for (j = 1; j < MAX_SERVICES; j++) {
+        if (compare_ts(last_hit, record->last_hit[j]) < 0)
           last_hit = record->last_hit[j];
       }
 
@@ -265,13 +284,16 @@ get_record(IPAddr *ip)
   }
 
   record->ip_addr = *ip;
-  for (i = 0; i < MAX_SERVICES; i++) {
+  for (i = 0; i < MAX_SERVICES; i++)
     record->last_hit[i] = INVALID_TS;
+  for (i = 0; i < MAX_SERVICES; i++)
     record->hits[i] = 0;
+  for (i = 0; i < MAX_SERVICES; i++)
     record->drops[i] = 0;
+  for (i = 0; i < MAX_SERVICES; i++)
     record->tokens[i] = max_tokens[i];
+  for (i = 0; i < MAX_SERVICES; i++)
     record->rate[i] = INVALID_RATE;
-  }
   record->ntp_timeout_rate = INVALID_RATE;
   record->drop_flags = 0;
 
index d7d40a0e9868c94ff38ef8bbaf169cf95e088292..2ea1f76391a70f34a46248a09d0fc37e5cb92a06 100644 (file)
@@ -73,7 +73,7 @@ test_unit(void)
   struct timespec ts, ts2;
   CLG_Service s;
   NTP_int64 ntp_ts;
-  IPAddr ip;
+  IPAddr ip, ip2;
   char *env, conf[][100] = {
     "clientloglimit 20000",
     "ratelimit interval 3 burst 4 leak 3",
@@ -90,6 +90,18 @@ test_unit(void)
 
   TEST_CHECK(ARR_GetSize(records) == 16);
 
+  TST_GetRandomAddress(&ip, IPADDR_INET4, 8);
+  while (UTI_CompareIPs(&ip, &ip2, NULL) == 0)
+    TST_GetRandomAddress(&ip2, IPADDR_INET4, 8);
+  TEST_CHECK(is_ip_equal(&ip, &ip));
+  TEST_CHECK(!is_ip_equal(&ip, &ip2));
+  TST_GetRandomAddress(&ip, IPADDR_INET6, 8);
+  TEST_CHECK(!is_ip_equal(&ip, &ip2));
+  while (UTI_CompareIPs(&ip, &ip2, NULL) == 0)
+    TST_GetRandomAddress(&ip2, IPADDR_INET6, 8);
+  TEST_CHECK(is_ip_equal(&ip, &ip));
+  TEST_CHECK(!is_ip_equal(&ip, &ip2));
+
   /* Expected format of the variable: ITERS:BITS */
   if ((env = getenv("BENCH_CLIENTLOG"))) {
     exit(!bench(env));