MEDIUM: server: switch conf.name to cebis_tree

This is used to index the server name and it contains a copy of the
pointer to the server's name in <id>. Changing that for a ceb_node placed
just before <id> saves 32 bytes to the struct server, which remains 3968
bytes large due to alignment. The proxy struct shrinks by 8 bytes to 3144.

It's worth noting that the current way duplicate names are handled remains
based on the previous mechanism where dups were permitted. Ideally we
should now reject them during insertion and use unique key trees instead.
This commit is contained in:
Willy Tarreau 2025-07-07 15:33:40 +02:00
parent 0e99f64fc6
commit 413e903a22
4 changed files with 14 additions and 21 deletions

View File

@ -463,7 +463,7 @@ struct proxy {
int line; /* line where the section appears */ int line; /* line where the section appears */
struct eb_root used_listener_id;/* list of listener IDs in use */ struct eb_root used_listener_id;/* list of listener IDs in use */
struct eb_root used_server_id; /* list of server IDs in use */ struct eb_root used_server_id; /* list of server IDs in use */
struct eb_root used_server_name; /* list of server names in use */ struct ceb_root *used_server_name; /* list of server names in use */
struct list bind; /* list of bind settings */ struct list bind; /* list of bind settings */
struct list listeners; /* list of listeners belonging to this frontend */ struct list listeners; /* list of listeners belonging to this frontend */
struct list errors; /* list of all custom error files */ struct list errors; /* list of all custom error files */

View File

@ -368,6 +368,7 @@ struct server {
unsigned long last_change; /* internal use only (not for stats purpose): last time the server state was changed, doesn't change often, not updated atomically on purpose */ unsigned long last_change; /* internal use only (not for stats purpose): last time the server state was changed, doesn't change often, not updated atomically on purpose */
char *id; /* just for identification */ char *id; /* just for identification */
uint32_t rid; /* revision: if id has been reused for a new server, rid won't match */ uint32_t rid; /* revision: if id has been reused for a new server, rid won't match */
unsigned iweight,uweight, cur_eweight; /* initial weight, user-specified weight, and effective weight */ unsigned iweight,uweight, cur_eweight; /* initial weight, user-specified weight, and effective weight */
unsigned wscore; /* weight score, used during srv map computation */ unsigned wscore; /* weight score, used during srv map computation */
@ -510,7 +511,7 @@ struct server {
struct { struct {
const char *file; /* file where the section appears */ const char *file; /* file where the section appears */
struct eb32_node id; /* place in the tree of used IDs */ struct eb32_node id; /* place in the tree of used IDs */
struct ebpt_node name; /* place in the tree of used names */ struct ceb_node name_node; /* place in the tree of used names, indexes <id> above, not unique, indexed in px->used_server_name */
int line; /* line where the section appears */ int line; /* line where the section appears */
} conf; /* config information */ } conf; /* config information */

View File

@ -36,6 +36,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include <import/cebis_tree.h>
#include <haproxy/acl.h> #include <haproxy/acl.h>
#include <haproxy/action.h> #include <haproxy/action.h>
#include <haproxy/api.h> #include <haproxy/api.h>
@ -3702,12 +3704,11 @@ out_uri_auth_compat:
/* Note: internal servers are not always registered and /* Note: internal servers are not always registered and
* they do not conflict. * they do not conflict.
*/ */
if (!newsrv->conf.name.node.leaf_p) if (!ceb_intree(&newsrv->conf.name_node))
continue; continue;
for (other_srv = newsrv; for (other_srv = newsrv;
(other_srv = container_of_safe(ebpt_prev_dup(&other_srv->conf.name), (other_srv = cebis_item_prev_dup(&curproxy->conf.used_server_name, conf.name_node, id, other_srv)); ) {
struct server, conf.name)); ) {
ha_alert("parsing [%s:%d] : %s '%s', another server named '%s' was already defined at line %d, please use distinct names.\n", ha_alert("parsing [%s:%d] : %s '%s', another server named '%s' was already defined at line %d, please use distinct names.\n",
newsrv->conf.file, newsrv->conf.line, newsrv->conf.file, newsrv->conf.line,
proxy_type_str(curproxy), curproxy->id, proxy_type_str(curproxy), curproxy->id,

View File

@ -3207,7 +3207,7 @@ struct server *srv_drop(struct server *srv)
//BUG_ON(ceb_intree(&srv->addr_node) || //BUG_ON(ceb_intree(&srv->addr_node) ||
// srv->idle_node.node.leaf_p || // srv->idle_node.node.leaf_p ||
// srv->conf.id.node.leaf_p || // srv->conf.id.node.leaf_p ||
// srv->conf.name.node.leaf_p); // ceb_intree(&srv->name_node));
guid_remove(&srv->guid); guid_remove(&srv->guid);
@ -3359,8 +3359,7 @@ static int _srv_parse_tmpl_init(struct server *srv, struct proxy *px)
/* Set the first server's ID. */ /* Set the first server's ID. */
_srv_parse_set_id_from_prefix(srv, srv->tmpl_info.prefix, srv->tmpl_info.nb_low); _srv_parse_set_id_from_prefix(srv, srv->tmpl_info.prefix, srv->tmpl_info.nb_low);
srv->conf.name.key = srv->id; cebis_item_insert(&curproxy->conf.used_server_name, conf.name_node, id, srv);
ebis_insert(&curproxy->conf.used_server_name, &srv->conf.name);
/* then create other servers from this one */ /* then create other servers from this one */
for (i = srv->tmpl_info.nb_low + 1; i <= srv->tmpl_info.nb_high; i++) { for (i = srv->tmpl_info.nb_low + 1; i <= srv->tmpl_info.nb_high; i++) {
@ -3384,8 +3383,7 @@ static int _srv_parse_tmpl_init(struct server *srv, struct proxy *px)
/* Set this new server ID. */ /* Set this new server ID. */
_srv_parse_set_id_from_prefix(newsrv, srv->tmpl_info.prefix, i); _srv_parse_set_id_from_prefix(newsrv, srv->tmpl_info.prefix, i);
newsrv->conf.name.key = newsrv->id; cebis_item_insert(&curproxy->conf.used_server_name, conf.name_node, id, newsrv);
ebis_insert(&curproxy->conf.used_server_name, &newsrv->conf.name);
} }
return i - srv->tmpl_info.nb_low; return i - srv->tmpl_info.nb_low;
@ -3993,8 +3991,7 @@ int parse_server(const char *file, int linenum, char **args,
_srv_parse_tmpl_init(newsrv, curproxy); _srv_parse_tmpl_init(newsrv, curproxy);
} }
else if (!(parse_flags & SRV_PARSE_DEFAULT_SERVER)) { else if (!(parse_flags & SRV_PARSE_DEFAULT_SERVER)) {
newsrv->conf.name.key = newsrv->id; cebis_item_insert(&curproxy->conf.used_server_name, conf.name_node, id, newsrv);
ebis_insert(&curproxy->conf.used_server_name, &newsrv->conf.name);
} }
/* If the server id is fixed, insert it in the proxy used_id tree. /* If the server id is fixed, insert it in the proxy used_id tree.
@ -4042,15 +4039,10 @@ struct server *server_find_by_id_unique(struct proxy *bk, int id, uint32_t rid)
*/ */
struct server *server_find_by_name(struct proxy *px, const char *name) struct server *server_find_by_name(struct proxy *px, const char *name)
{ {
struct ebpt_node *node;
struct server *cursrv;
if (!px) if (!px)
return NULL; return NULL;
node = ebis_lookup(&px->conf.used_server_name, name); return cebis_item_lookup(&px->conf.used_server_name, conf.name_node, id, name, struct server);
cursrv = node ? container_of(node, struct server, conf.name) : NULL;
return cursrv;
} }
/* /*
@ -6244,11 +6236,10 @@ static int cli_parse_add_server(char **args, char *payload, struct appctx *appct
srv->conf.id.key = srv->puid = next_id; srv->conf.id.key = srv->puid = next_id;
} }
srv->conf.name.key = srv->id;
/* insert the server in the backend trees */ /* insert the server in the backend trees */
eb32_insert(&be->conf.used_server_id, &srv->conf.id); eb32_insert(&be->conf.used_server_id, &srv->conf.id);
ebis_insert(&be->conf.used_server_name, &srv->conf.name); cebis_item_insert(&be->conf.used_server_name, conf.name_node, id, srv);
/* addr_key could be NULL if FQDN resolution is postponed (ie: add server from cli) */ /* addr_key could be NULL if FQDN resolution is postponed (ie: add server from cli) */
if (srv->addr_key) if (srv->addr_key)
cebuis_item_insert(&be->used_server_addr, addr_node, addr_key, srv); cebuis_item_insert(&be->used_server_addr, addr_node, addr_key, srv);
@ -6467,7 +6458,7 @@ static int cli_parse_delete_server(char **args, char *payload, struct appctx *ap
/* remove srv from addr_node tree */ /* remove srv from addr_node tree */
eb32_delete(&srv->conf.id); eb32_delete(&srv->conf.id);
ebpt_delete(&srv->conf.name); cebis_item_delete(&be->conf.used_server_name, conf.name_node, id, srv);
cebuis_item_delete(&be->used_server_addr, addr_node, addr_key, srv); cebuis_item_delete(&be->used_server_addr, addr_node, addr_key, srv);
/* remove srv from idle_node tree for idle conn cleanup */ /* remove srv from idle_node tree for idle conn cleanup */