MINOR: server: move actconns to the per-thread structure
The actconns list creates massive contention on low server counts because
it's in fact a list of streams using a server, all threads compete on the
list's head and it's still possible to see some watchdog panics on 48
threads under extreme contention with 47 threads trying to add and one
thread trying to delete.
Moving this list per thread is trivial because it's only used by
srv_shutdown_streams(), which simply required to iterate over the list.
The field was renamed to "streams" as it's really a list of streams
rather than a list of connections.
(cherry picked from commit d4e78d873cecf9938885c90e736f8b761a35fb55)
[wt: for 2.3 and older, this is a simplified version. We don't want to
touch all the server initialization code and sequence with the risks
of causing new trouble, so instead we declare actconns as an array
of the maximum number of supported threads, this will eat a bit more
memory on smaller machines but will remain safe. Those building with
MAX_THREADS close or equal to their target number of threads may even
save some RAM compared to 2.4. The only servers not initialized via
new_server() are the two Lua socket servers, and they've been handled
here]
Signed-off-by: Willy Tarreau <w@1wt.eu>
diff --git a/src/server.c b/src/server.c
index 13eb676..c01c948 100644
--- a/src/server.c
+++ b/src/server.c
@@ -865,10 +865,12 @@
{
struct stream *stream;
struct mt_list *elt1, elt2;
+ int thr;
- mt_list_for_each_entry_safe(stream, &srv->actconns, by_srv, elt1, elt2)
- if (stream->srv_conn == srv)
- stream_shutdown(stream, why);
+ for (thr = 0; thr < global.nbthread; thr++)
+ mt_list_for_each_entry_safe(stream, &srv->actconns[thr], by_srv, elt1, elt2)
+ if (stream->srv_conn == srv)
+ stream_shutdown(stream, why);
}
/* Shutdown all connections of all backup servers of a proxy. The caller must
@@ -1718,6 +1720,7 @@
struct server *new_server(struct proxy *proxy)
{
struct server *srv;
+ int i;
srv = calloc(1, sizeof *srv);
if (!srv)
@@ -1725,7 +1728,8 @@
srv->obj_type = OBJ_TYPE_SERVER;
srv->proxy = proxy;
- MT_LIST_INIT(&srv->actconns);
+ for (i = 0; i < MAX_THREADS; i++)
+ MT_LIST_INIT(&srv->actconns[i]);
srv->pendconns = EB_ROOT;
srv->next_state = SRV_ST_RUNNING; /* early server setup */