From: Willy Tarreau Date: Sat, 15 Mar 2014 06:22:35 +0000 (+0100) Subject: MEDIUM: proxy: create a tree to store proxies by name X-Git-Tag: v1.5-dev23~143 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f79d950163df553b98e486610a196b9cd98db43d;p=thirdparty%2Fhaproxy.git MEDIUM: proxy: create a tree to store proxies by name Large configurations can take time to parse when thousands of backends are in use. Let's store all the proxies in trees. findproxy_mode() has been modified to use the tree for lookups, which has divided the parsing time by about 2.5. But many lookups are still present at many places and need to be dealt with. --- diff --git a/include/proto/proxy.h b/include/proto/proxy.h index 4a4b2857f1..116c00a16c 100644 --- a/include/proto/proxy.h +++ b/include/proto/proxy.h @@ -30,6 +30,11 @@ #include #include +extern struct proxy *proxy; +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 struct eb_root proxy_by_name; /* tree of proxies sorted by name */ + int start_proxies(int verbose); struct task *manage_proxy(struct task *t); void soft_stop(void); @@ -42,6 +47,7 @@ int session_set_backend(struct session *s, struct proxy *be); const char *proxy_cap_str(int cap); const char *proxy_mode_str(int mode); +void proxy_store_name(struct proxy *px); struct proxy *findproxy_mode(const char *name, int mode, int cap); struct proxy *findproxy(const char *name, int cap); struct server *findserver(const struct proxy *px, const char *name); diff --git a/include/types/proxy.h b/include/types/proxy.h index af2a3abd3d..1a778bd911 100644 --- a/include/types/proxy.h +++ b/include/types/proxy.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -363,6 +364,7 @@ struct proxy { struct list bind; /* list of bind settings */ struct list listeners; /* list of listeners belonging to this frontend */ struct arg_list args; /* sample arg list that need to be resolved */ + struct ebpt_node by_name; /* proxies are stored sorted by name here */ char *logformat_string; /* log format string */ char *lfs_file; /* file name where the logformat string appears (strdup) */ int lfs_line; /* file name where the logformat string appears */ @@ -423,10 +425,6 @@ struct redirect_rule { char *cookie_str; }; -extern struct proxy *proxy; -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 */ - #endif /* _TYPES_PROXY_H */ /* diff --git a/src/cfgparse.c b/src/cfgparse.c index f13b9679d1..ceaa96e4a9 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -1826,6 +1826,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) curproxy->last_change = now.tv_sec; curproxy->id = strdup(args[1]); curproxy->cap = rc; + proxy_store_name(curproxy); /* parse the listener address if any */ if ((curproxy->cap & PR_CAP_FE) && *args[2]) { diff --git a/src/proxy.c b/src/proxy.c index ef0f63de1f..3cbc1b4ac2 100644 --- a/src/proxy.c +++ b/src/proxy.c @@ -44,6 +44,7 @@ int listeners; /* # of proxy listeners, set by cfgparse */ struct proxy *proxy = NULL; /* list of all existing proxies */ 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 */ unsigned int error_snapshot_id = 0; /* global ID assigned to each error then incremented */ /* @@ -278,6 +279,15 @@ static int proxy_parse_rate_limit(char **args, int section, struct proxy *proxy, return retval; } +/* This function inserts proxy into the tree of known proxies. The proxy's + * name is used as the storing key so it must already have been initialized. + */ +void proxy_store_name(struct proxy *px) +{ + px->conf.by_name.key = px->id; + ebis_insert(&proxy_by_name, &px->conf.by_name); +} + /* * This function finds a proxy with matching name, mode and with satisfying * capabilities. It also checks if there are more matching proxies with @@ -287,9 +297,15 @@ static int proxy_parse_rate_limit(char **args, int section, struct proxy *proxy, struct proxy *findproxy_mode(const char *name, int mode, int cap) { struct proxy *curproxy, *target = NULL; + struct ebpt_node *node; - for (curproxy = proxy; curproxy; curproxy = curproxy->next) { - if ((curproxy->cap & cap)!=cap || strcmp(curproxy->id, name)) + for (node = ebis_lookup(&proxy_by_name, name); node; node = ebpt_next(node)) { + curproxy = container_of(node, struct proxy, conf.by_name); + + if (strcmp(curproxy->id, name) != 0) + break; + + if ((curproxy->cap & cap) != cap) continue; if (curproxy->mode != mode &&