From: Yann Ylavic Date: Fri, 3 Dec 2021 13:25:51 +0000 (+0000) Subject: mpm_event: Follow up to r1894285: new MaxSpareThreads heuristics. X-Git-Tag: 2.5.0-alpha2-ci-test-only~668 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1aff1980f3399652aeec6faeecddf736da117ec7;p=thirdparty%2Fapache%2Fhttpd.git mpm_event: Follow up to r1894285: new MaxSpareThreads heuristics. When at MaxSpareThreads, instead of deferring the stop if we are close to active/server limit let's wait for the pending exits to complete. This way we always and accurately account for slow-to-exit processes to avoid filling up the scoreboard, whether at the limits or not. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1895553 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/mpm/event/event.c b/server/mpm/event/event.c index c32f07da1b8..c3f4775ea9a 100644 --- a/server/mpm/event/event.c +++ b/server/mpm/event/event.c @@ -3179,16 +3179,15 @@ static void perform_idle_server_maintenance(int child_bucket) } } - if (idle_thread_count > max_spare_threads / num_buckets) - { + if (idle_thread_count > max_spare_threads / num_buckets) { /* * Child processes that we ask to shut down won't die immediately * but may stay around for a long time when they finish their * requests. If the server load changes many times, many such * gracefully finishing processes may accumulate, filling up the * scoreboard. To avoid running out of scoreboard entries, we - * don't shut down more processes when the total number of processes - * is high, until there are more than max_workers/4 idle threads. + * don't shut down more processes if there are stopping ones + * already (i.e. active_daemons < total_daemons). * * XXX It would be nice if we could * XXX - kill processes without keepalive connections first @@ -3196,26 +3195,21 @@ static void perform_idle_server_maintenance(int child_bucket) * XXX depending on server load, later be able to resurrect them * or kill them */ - if ((retained->total_daemons <= active_daemons_limit - && retained->total_daemons < server_limit) - /* The above test won't transition from true to false until a child - * exits by itself (i.e. MaxRequestsPerChild reached), so the below - * test makes sure that the situation unblocks when the load falls - * significantly (regardless of MaxRequestsPerChild, e.g. 0) */ - || idle_thread_count > max_workers/4 / num_buckets) { - /* Kill off one child */ + int ignore = (retained->active_daemons < retained->total_daemons); + ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, ap_server_conf, + "%shutting down one child: " + "active daemons %d / active limit %d / " + "total daemons %d / ServerLimit %d / " + "idle threads %d / max workers %d", + (ignore) ? "Not s" : "S", + retained->active_daemons, active_daemons_limit, + retained->total_daemons, server_limit, + idle_thread_count, max_workers); + if (!ignore) { ap_mpm_podx_signal(retained->buckets[child_bucket].pod, AP_MPM_PODX_GRACEFUL); - retained->idle_spawn_rate[child_bucket] = 1; - } else { - /* Still busy enough, don't kill */ - ap_log_error(APLOG_MARK, APLOG_TRACE5, 0, ap_server_conf, - "Not shutting down child: total daemons %d / " - "active limit %d / ServerLimit %d / " - "idle threads %d / max workers %d", - retained->total_daemons, active_daemons_limit, - server_limit, idle_thread_count, max_workers); } + retained->idle_spawn_rate[child_bucket] = 1; } else if (idle_thread_count < min_spare_threads / num_buckets) { if (active_thread_count >= max_workers / num_buckets) {