mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-20 13:21:29 +02:00
MEDIUM: proxy: switch conf.name to cebis_tree
This is used to index the proxy's name and it contains a copy of the pointer to the proxy's name in <id>. Changing that for a ceb_node placed just before <id> saves 32 bytes to the struct proxy, which is now 3112 bytes large. Here we need to continue to support duplicates since they're still allowed between type-incompatible proxies. Interestingly, the use of cebis_next_dup() instead of cebis_next() in proxy_find_by_name() allows us to get rid of an strcmp() that was performed for each use_backend rule. A test with a large config (100k backends) shows that we can get 3% extra performance on a config involving a static use_backend rule (3.09M to 3.18M rps), and even 4.5% on a dynamic rule selecting a random backend (2.47M to 2.59M).
This commit is contained in:
parent
fdf6fd5b45
commit
d0d60a007d
@ -396,7 +396,8 @@ struct proxy {
|
|||||||
} timeout;
|
} timeout;
|
||||||
__decl_thread(HA_RWLOCK_T lock); /* may be taken under the server's lock */
|
__decl_thread(HA_RWLOCK_T lock); /* may be taken under the server's lock */
|
||||||
|
|
||||||
char *id, *desc; /* proxy id (name) and description */
|
char *id; /* proxy id (name), indexed by <conf.name_node> below */
|
||||||
|
char *desc; /* proxy description */
|
||||||
struct proxy_per_tgroup *per_tgrp; /* array of per-tgroup stuff such as queues */
|
struct proxy_per_tgroup *per_tgrp; /* array of per-tgroup stuff such as queues */
|
||||||
unsigned int queueslength; /* Sum of the length of each queue */
|
unsigned int queueslength; /* Sum of the length of each queue */
|
||||||
int totpend; /* total number of pending connections on this instance (for stats) */
|
int totpend; /* total number of pending connections on this instance (for stats) */
|
||||||
@ -468,7 +469,7 @@ struct proxy {
|
|||||||
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 */
|
||||||
struct arg_list args; /* sample arg list that need to be resolved */
|
struct arg_list args; /* sample arg list that need to be resolved */
|
||||||
struct ebpt_node by_name; /* proxies are stored sorted by name here */
|
struct ceb_node name_node; /* proxies are stored sorted by name here; indexes <id> below */
|
||||||
struct list lf_checks; /* list of logformats found in the proxy section that needs to be checked during postparse */
|
struct list lf_checks; /* list of logformats found in the proxy section that needs to be checked during postparse */
|
||||||
struct log_steps log_steps; /* bitfield of log origins where log should be generated during request handling */
|
struct log_steps log_steps; /* bitfield of log origins where log should be generated during request handling */
|
||||||
const char *file_prev; /* file of the previous instance found with the same name, or NULL */
|
const char *file_prev; /* file of the previous instance found with the same name, or NULL */
|
||||||
|
@ -36,7 +36,7 @@ extern struct proxy *proxies_list;
|
|||||||
extern struct list proxies;
|
extern struct list proxies;
|
||||||
extern struct eb_root used_proxy_id; /* list of proxy IDs in use */
|
extern struct eb_root used_proxy_id; /* list of proxy IDs in use */
|
||||||
extern unsigned int error_snapshot_id; /* global ID assigned to each error then incremented */
|
extern unsigned int error_snapshot_id; /* global ID assigned to each error then incremented */
|
||||||
extern struct eb_root proxy_by_name; /* tree of proxies sorted by name */
|
extern struct ceb_root *proxy_by_name; /* tree of proxies sorted by name */
|
||||||
|
|
||||||
extern const struct cfg_opt cfg_opts[];
|
extern const struct cfg_opt cfg_opts[];
|
||||||
extern const struct cfg_opt cfg_opts2[];
|
extern const struct cfg_opt cfg_opts2[];
|
||||||
|
36
src/proxy.c
36
src/proxy.c
@ -16,8 +16,8 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <import/cebis_tree.h>
|
||||||
#include <import/eb32tree.h>
|
#include <import/eb32tree.h>
|
||||||
#include <import/ebistree.h>
|
|
||||||
|
|
||||||
#include <haproxy/acl.h>
|
#include <haproxy/acl.h>
|
||||||
#include <haproxy/api.h>
|
#include <haproxy/api.h>
|
||||||
@ -62,8 +62,8 @@ int listeners; /* # of proxy listeners, set by cfgparse */
|
|||||||
struct proxy *proxies_list = NULL; /* list of main proxies */
|
struct proxy *proxies_list = NULL; /* list of main proxies */
|
||||||
struct list proxies = LIST_HEAD_INIT(proxies); /* list of all proxies */
|
struct list proxies = LIST_HEAD_INIT(proxies); /* list of all proxies */
|
||||||
struct eb_root used_proxy_id = EB_ROOT; /* list of proxy IDs in use */
|
struct eb_root used_proxy_id = EB_ROOT; /* list of proxy IDs in use */
|
||||||
struct eb_root proxy_by_name = EB_ROOT; /* tree of proxies sorted by name */
|
struct ceb_root *proxy_by_name = NULL; /* tree of proxies sorted by name */
|
||||||
struct eb_root defproxy_by_name = EB_ROOT; /* tree of default proxies sorted by name (dups possible) */
|
struct ceb_root *defproxy_by_name = NULL; /* tree of default proxies sorted by name (dups possible) */
|
||||||
struct proxy *orphaned_default_proxies = NULL; /* deleted ones with refcount != 0 */
|
struct proxy *orphaned_default_proxies = NULL; /* deleted ones with refcount != 0 */
|
||||||
unsigned int error_snapshot_id = 0; /* global ID assigned to each error then incremented */
|
unsigned int error_snapshot_id = 0; /* global ID assigned to each error then incremented */
|
||||||
|
|
||||||
@ -217,7 +217,7 @@ static inline void proxy_free_common(struct proxy *px)
|
|||||||
struct lf_expr *lf, *lfb;
|
struct lf_expr *lf, *lfb;
|
||||||
|
|
||||||
/* note that the node's key points to p->id */
|
/* note that the node's key points to p->id */
|
||||||
ebpt_delete(&px->conf.by_name);
|
cebis_item_delete((px->cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name, conf.name_node, id, px);
|
||||||
ha_free(&px->id);
|
ha_free(&px->id);
|
||||||
LIST_DEL_INIT(&px->global_list);
|
LIST_DEL_INIT(&px->global_list);
|
||||||
drop_file_name(&px->conf.file);
|
drop_file_name(&px->conf.file);
|
||||||
@ -1172,10 +1172,9 @@ static int proxy_parse_guid(char **args, int section_type, struct proxy *curpx,
|
|||||||
*/
|
*/
|
||||||
void proxy_store_name(struct proxy *px)
|
void proxy_store_name(struct proxy *px)
|
||||||
{
|
{
|
||||||
struct eb_root *root = (px->cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name;
|
struct ceb_root **root = (px->cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name;
|
||||||
|
|
||||||
px->conf.by_name.key = px->id;
|
cebis_item_insert(root, conf.name_node, id, px);
|
||||||
ebis_insert(root, &px->conf.by_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns a pointer to the first proxy matching capabilities <cap> and id
|
/* Returns a pointer to the first proxy matching capabilities <cap> and id
|
||||||
@ -1219,16 +1218,11 @@ struct proxy *proxy_find_by_name(const char *name, int cap, int table)
|
|||||||
return curproxy;
|
return curproxy;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct eb_root *root;
|
struct ceb_root **root;
|
||||||
struct ebpt_node *node;
|
|
||||||
|
|
||||||
root = (cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name;
|
root = (cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name;
|
||||||
for (node = ebis_lookup(root, name); node; node = ebpt_next(node)) {
|
for (curproxy = cebis_item_lookup(root, conf.name_node, id, name, struct proxy);
|
||||||
curproxy = container_of(node, struct proxy, conf.by_name);
|
curproxy; curproxy = cebis_item_next_dup(root, conf.name_node, id, curproxy)) {
|
||||||
|
|
||||||
if (strcmp(curproxy->id, name) != 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if ((curproxy->cap & cap) != cap)
|
if ((curproxy->cap & cap) != cap)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1583,7 +1577,8 @@ void proxy_destroy_defaults(struct proxy *px)
|
|||||||
if (!(px->cap & PR_CAP_DEF))
|
if (!(px->cap & PR_CAP_DEF))
|
||||||
return;
|
return;
|
||||||
BUG_ON(px->conf.refcount != 0);
|
BUG_ON(px->conf.refcount != 0);
|
||||||
ebpt_delete(&px->conf.by_name);
|
cebis_item_delete((px->cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name,
|
||||||
|
conf.name_node, id, px);
|
||||||
proxy_free_defaults(px);
|
proxy_free_defaults(px);
|
||||||
free(px);
|
free(px);
|
||||||
}
|
}
|
||||||
@ -1593,14 +1588,11 @@ void proxy_destroy_defaults(struct proxy *px)
|
|||||||
*/
|
*/
|
||||||
void proxy_destroy_all_unref_defaults()
|
void proxy_destroy_all_unref_defaults()
|
||||||
{
|
{
|
||||||
struct ebpt_node *n;
|
|
||||||
struct proxy *px, *nx;
|
struct proxy *px, *nx;
|
||||||
|
|
||||||
n = ebpt_first(&defproxy_by_name);
|
for (px = cebis_item_first(&defproxy_by_name, conf.name_node, id, struct proxy); px; px = nx) {
|
||||||
while (n) {
|
|
||||||
px = container_of(n, struct proxy, conf.by_name);
|
|
||||||
BUG_ON(!(px->cap & PR_CAP_DEF));
|
BUG_ON(!(px->cap & PR_CAP_DEF));
|
||||||
n = ebpt_next(n);
|
nx = cebis_item_next(&defproxy_by_name, conf.name_node, id, px);
|
||||||
if (!px->conf.refcount)
|
if (!px->conf.refcount)
|
||||||
proxy_destroy_defaults(px);
|
proxy_destroy_defaults(px);
|
||||||
}
|
}
|
||||||
@ -1624,7 +1616,7 @@ void proxy_unref_or_destroy_defaults(struct proxy *px)
|
|||||||
if (!px || !(px->cap & PR_CAP_DEF))
|
if (!px || !(px->cap & PR_CAP_DEF))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ebpt_delete(&px->conf.by_name);
|
cebis_item_delete((px->cap & PR_CAP_DEF) ? &defproxy_by_name : &proxy_by_name, conf.name_node, id, px);
|
||||||
if (px->conf.refcount) {
|
if (px->conf.refcount) {
|
||||||
/* still referenced just append it to the orphaned list */
|
/* still referenced just append it to the orphaned list */
|
||||||
px->next = orphaned_default_proxies;
|
px->next = orphaned_default_proxies;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user