]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: guid: switch guid to more compact cebuis_tree
authorWilly Tarreau <w@1wt.eu>
Mon, 17 Feb 2025 08:39:04 +0000 (09:39 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 16 Sep 2025 07:23:46 +0000 (09:23 +0200)
The current guid struct size is 56 bytes. Once reduced using compact
trees, it goes down to 32 (almost half). We're not on a critical path
and size matters here, so better switch to this.

It's worth noting that the name part could also be stored in the
guid_node at the end to save 8 extra byte (no pointer needed anymore),
however the purpose of this struct is to be embedded into other ones,
which is not compatible with having a dynamic size.

Affected struct sizes in bytes:

           Before     After   Diff
  server    4032       4032     0*
  proxy     3184       3160    -24
  listener   752        728    -24

*: struct server is full of holes and padding (176 bytes) and is
64-byte aligned. Moving the guid_node elsewhere such as after sess_conn
reduces it to 3968, or one less cache line. There's no point in moving
anything now because forthcoming patches will arrange other parts.

include/haproxy/guid-t.h
include/haproxy/guid.h
src/counters.c
src/guid.c
src/stats-file.c

index 9eea355d174e09ee03b481ff7b0ee814c625cc70..f77d921b2ced32b8eb6fc4dc2e6e21cb3e565981 100644 (file)
@@ -1,14 +1,15 @@
 #ifndef _HAPROXY_GUID_T_H
 #define _HAPROXY_GUID_T_H
 
-#include <import/ebtree-t.h>
+#include <import/cebtree.h>
 #include <haproxy/obj_type-t.h>
 
 /* Maximum GUID size excluding final '\0' */
 #define GUID_MAX_LEN 127
 
 struct guid_node {
-       struct ebpt_node node;   /* attach point into GUID global tree */
+       struct ceb_node node;    /* attach point into GUID global tree */
+       char *key;               /* the key itself */
        enum obj_type *obj_type; /* pointer to GUID obj owner */
 };
 
index f57a21d76c5ee7807fb033ad0aefc77039628c74..585883472c1d33991e25dd631adf6e1e1e34e652 100644 (file)
@@ -17,7 +17,7 @@ struct guid_node *guid_lookup(const char *uid);
  */
 static inline const char *guid_get(const struct guid_node *guid)
 {
-       return guid->node.key;
+       return guid->key;
 }
 
 int guid_is_valid_fmt(const char *uid, char **errmsg);
index 8506e3b5bcdf88d18f6219e3bf0c0e04aa2cb9a1..1f6238c3714ec676e8fd10b85c206665bbabb00f 100644 (file)
@@ -83,7 +83,7 @@ static int _counters_shared_prepare(struct counters_shared *shared,
        struct be_counters_shared *be_shared;
        int it = 0;
 
-       if (!guid->node.key || !shm_stats_file_hdr)
+       if (!guid->key || !shm_stats_file_hdr)
                shared->flags |= COUNTERS_SHARED_F_LOCAL;
 
        while (it < global.nbtgroups) {
index 9f29cfec0e865150bebdce205f8c34f48046d141..f26f53ea3093b550a3fe82de97ae282eb67311dd 100644 (file)
@@ -1,6 +1,6 @@
 #include <haproxy/guid.h>
 
-#include <import/ebistree.h>
+#include <import/cebis_tree.h>
 #include <haproxy/listener-t.h>
 #include <haproxy/obj_type.h>
 #include <haproxy/proxy.h>
@@ -9,15 +9,16 @@
 #include <haproxy/thread.h>
 
 /* GUID global tree */
-struct eb_root guid_tree = EB_ROOT_UNIQUE;
+struct ceb_root *guid_tree = NULL;
 __decl_thread(HA_RWLOCK_T guid_lock);
+
+/* note: touched under the guid_lock */
 static int _guid_count = 0;
 
 /* Initialize <guid> members. */
 void guid_init(struct guid_node *guid)
 {
-       guid->node.key = NULL;
-       guid->node.node.leaf_p = NULL;
+       memset(guid, 0, sizeof(*guid));
 }
 
 /* Insert <objt> into GUID global tree with key <uid>. Must only be called on
@@ -30,7 +31,6 @@ int guid_insert(enum obj_type *objt, const char *uid, char **errmsg)
 {
        struct guid_node *guid = NULL;
        struct guid_node *dup;
-       struct ebpt_node *node;
        char *dup_name = NULL;
 
        if (!guid_is_valid_fmt(uid, errmsg))
@@ -55,16 +55,15 @@ int guid_insert(enum obj_type *objt, const char *uid, char **errmsg)
                return 0;
        }
 
-       guid->node.key = strdup(uid);
-       if (!guid->node.key) {
+       guid->key = strdup(uid);
+       if (!guid->key) {
                memprintf(errmsg, "key alloc failure");
                goto err;
        }
 
        HA_RWLOCK_WRLOCK(GUID_LOCK, &guid_lock);
-       node = ebis_insert(&guid_tree, &guid->node);
-       if (node != &guid->node) {
-               dup = ebpt_entry(node, struct guid_node, node);
+       dup = cebuis_item_insert(&guid_tree, node, key, guid);
+       if (dup != guid) {
                HA_RWLOCK_WRUNLOCK(GUID_LOCK, &guid_lock);
                dup_name = guid_name(dup);
                memprintf(errmsg, "duplicate entry with %s", dup_name);
@@ -79,10 +78,8 @@ int guid_insert(enum obj_type *objt, const char *uid, char **errmsg)
 
  err:
        if (guid)
-               ha_free(&guid->node.key);
+               ha_free(&guid->key);
        ha_free(&dup_name);
-       if (guid)
-               guid->node.key = NULL; /* so that we can check that guid is not in a tree */
        return 1;
 }
 
@@ -92,10 +89,10 @@ int guid_insert(enum obj_type *objt, const char *uid, char **errmsg)
 void guid_remove(struct guid_node *guid)
 {
        HA_RWLOCK_WRLOCK(GUID_LOCK, &guid_lock);
-       ebpt_delete(&guid->node);
-       if (guid->node.key)
+       if (guid->key)
                _guid_count--;
-       ha_free(&guid->node.key);
+       cebuis_item_delete(&guid_tree, node, key, guid);
+       ha_free(&guid->key);
        HA_RWLOCK_WRUNLOCK(GUID_LOCK, &guid_lock);
 }
 
@@ -105,7 +102,6 @@ void guid_remove(struct guid_node *guid)
  */
 struct guid_node *guid_lookup(const char *uid)
 {
-       struct ebpt_node *node = NULL;
        struct guid_node *guid = NULL;
 
        /* For now, guid_lookup() is only used during startup in single-thread
@@ -114,10 +110,7 @@ struct guid_node *guid_lookup(const char *uid)
         */
        BUG_ON(!(global.mode & MODE_STARTING));
 
-       node = ebis_lookup(&guid_tree, uid);
-       if (node)
-               guid = ebpt_entry(node, struct guid_node, node);
-
+       guid = cebuis_item_lookup(&guid_tree, node, key, uid, struct guid_node);
        return guid;
 }
 
index 578646cd2a8ec36ba8a20a889591afe777138b9c..3e50f358894c3fc469b225f3d1c91f3c226e9c7c 100644 (file)
@@ -65,10 +65,10 @@ int stats_dump_fields_file(struct buffer *out,
        }
 
        /* Skip objects without GUID. */
-       if (!guid->node.key)
+       if (!guid->key)
                return 1;
 
-       chunk_appendf(out, "%s,", (char *)guid->node.key);
+       chunk_appendf(out, "%s,", (char *)guid->key);
 
        for (i = 0; i < stats_count; ++i) {
                /* Empty field for stats-file is used to skip its output,