[MEDIUM] improve behaviour with large number of servers per proxy
When a very large number of servers is configured (thousands),
shutting down many of them at once could lead to large number
of calls to recalc_server_map() which already takes some time.
This would result in an O(N^3) computation time, leading to
noticeable pauses on slow embedded CPUs on test platforms.
Instead, mark the map as dirty and recalc it only when needed.
diff --git a/src/backend.c b/src/backend.c
index 8abaf1c..da8b8ac 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -90,6 +90,7 @@
tot = 1; /* the first server is enough */
} else {
px->srv_map_sz = 0;
+ px->map_state &= ~PR_MAP_RECALC;
return;
}
@@ -130,6 +131,7 @@
best->wscore -= tot;
}
px->srv_map_sz = tot;
+ px->map_state &= ~PR_MAP_RECALC;
}
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 39abbc3..967b9ca 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2637,6 +2637,7 @@
curproxy->srv_map = (struct server **)calloc(act, sizeof(struct server *));
/* recounts servers and their weights */
+ curproxy->map_state = PR_MAP_RECALC;
recount_servers(curproxy);
recalc_server_map(curproxy);
}
diff --git a/src/checks.c b/src/checks.c
index 4c8a009..2c581ef 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -46,7 +46,8 @@
/* Sets server <s> down, notifies by all available means, recounts the
* remaining servers on the proxy and transfers queued sessions whenever
- * possible to other servers.
+ * possible to other servers. It automatically recomputes the number of
+ * servers, but not the map.
*/
static void set_server_down(struct server *s)
{
@@ -58,7 +59,7 @@
if (s->health == s->rise) {
recount_servers(s->proxy);
- recalc_server_map(s->proxy);
+ s->proxy->map_state |= PR_MAP_RECALC;
/* we might have sessions queued on this server and waiting for
* a connection. Those which are redispatchable will be queued
@@ -454,7 +455,7 @@
int xferred;
recount_servers(s->proxy);
- recalc_server_map(s->proxy);
+ s->proxy->map_state |= PR_MAP_RECALC;
/* check if we can handle some connections queued at the proxy. We
* will take as many as we can handle.
diff --git a/src/proto_http.c b/src/proto_http.c
index 9044d5d..f717bdf 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -3848,6 +3848,9 @@
case DATA_ST_PX_BE:
/* print the backend */
if (px->cap & PR_CAP_BE) {
+ if (px->map_state & PR_MAP_RECALC)
+ recalc_server_map(px);
+
chunk_printf(&msg, sizeof(trash),
/* name */
"<tr align=center class=\"backend\"><td>Backend</td>"