From: Greg Ames Date: Sun, 5 Aug 2001 18:08:49 +0000 (+0000) Subject: Speed up the server's response to a spike in incoming workload X-Git-Tag: 2.0.23~62 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ea0bdc760d50572aff8671eb7505d03fc308f9cf;p=apache Speed up the server's response to a spike in incoming workload or restarts. New processes aren't able to start all their threads right away if other dying processes share the same scoreboard real estate. So give empty process slots in the scoreboard top priority. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@89928 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 26dd0c0c61..be88dea077 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,9 @@ Changes with Apache 2.0.23-dev + *) Speed up the server's response to a spike in incoming workload + or restarts by assigning empty scoreboard slots to new processes + when they are available. [Greg Ames] + *) Add a handler to mod_includes.c. This handler is designed to implement the XbitHack directive. This can't be done with a fixup, because we need to check the content-type, which is diff --git a/server/mpm/threaded/threaded.c b/server/mpm/threaded/threaded.c index 76c45d4a5b..68d7c63bbb 100644 --- a/server/mpm/threaded/threaded.c +++ b/server/mpm/threaded/threaded.c @@ -973,6 +973,7 @@ static void perform_idle_server_maintenance(void) worker_score *ws; process_score *ps; int free_length; + int totally_free_length = 0; int free_slots[MAX_SPAWN_RATE]; int last_non_dead; int total_non_dead; @@ -993,16 +994,21 @@ static void perform_idle_server_maintenance(void) int status = SERVER_DEAD; int any_dying_threads = 0; int any_dead_threads = 0; + int all_dead_threads = 1; - if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate) + if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate) break; ps = &ap_scoreboard_image->parent[i]; for (j = 0; j < ap_threads_per_child; j++) { ws = &ap_scoreboard_image->servers[i][j]; status = ws->status; + /* XXX any_dying_threads is probably no longer needed GLA */ any_dying_threads = any_dying_threads || (status == SERVER_GRACEFUL); any_dead_threads = any_dead_threads || (status == SERVER_DEAD); + all_dead_threads = all_dead_threads && + (status == SERVER_DEAD || + status == SERVER_GRACEFUL); /* We consider a starting server as idle because we started it * at least a cycle ago, and if it still hasn't finished starting @@ -1020,13 +1026,28 @@ static void perform_idle_server_maintenance(void) ++idle_thread_count; } } - /* XXX any_dead_threads may not be needed any more GLA */ - if (any_dead_threads && free_length < idle_spawn_rate + if (any_dead_threads && totally_free_length < idle_spawn_rate && (!ps->pid /* no process in the slot */ || ps->quiescing)) { /* or at least one is going away */ - free_slots[free_length] = i; + if (all_dead_threads) { + /* great! we prefer these, because the new process can + * start more threads sooner. So prioritize this slot + * by putting it ahead of any slots with active threads. + * + * first, make room by moving a slot that's potentially still + * in use to the end of the array + */ + free_slots[free_length] = free_slots[totally_free_length]; + free_slots[totally_free_length++] = i; + } + else { + /* slot is still in use - back of the bus + */ + free_slots[free_length] = i; + } ++free_length; } + /* XXX if (!ps->quiescing) is probably more reliable GLA */ if (!any_dying_threads) { last_non_dead = i; ++total_non_dead; @@ -1057,7 +1078,9 @@ static void perform_idle_server_maintenance(void) idle_spawn_rate = 1; } else { - + if (free_length > idle_spawn_rate) { + free_length = idle_spawn_rate; + } if (idle_spawn_rate >= 8) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf, "server seems busy, (you may need " diff --git a/server/mpm/worker/worker.c b/server/mpm/worker/worker.c index 668a6c61ee..b272342293 100644 --- a/server/mpm/worker/worker.c +++ b/server/mpm/worker/worker.c @@ -1023,6 +1023,7 @@ static void perform_idle_server_maintenance(void) worker_score *ws; process_score *ps; int free_length; + int totally_free_length = 0; int free_slots[MAX_SPAWN_RATE]; int last_non_dead; int total_non_dead; @@ -1043,16 +1044,21 @@ static void perform_idle_server_maintenance(void) int status = SERVER_DEAD; int any_dying_threads = 0; int any_dead_threads = 0; + int all_dead_threads = 1; - if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate) + if (i >= ap_max_daemons_limit && totally_free_length == idle_spawn_rate) break; ps = &ap_scoreboard_image->parent[i]; for (j = 0; j < ap_threads_per_child; j++) { ws = &ap_scoreboard_image->servers[i][j]; status = ws->status; + /* XXX any_dying_threads is probably no longer needed GLA */ any_dying_threads = any_dying_threads || (status == SERVER_GRACEFUL); any_dead_threads = any_dead_threads || (status == SERVER_DEAD); + all_dead_threads = all_dead_threads && + (status == SERVER_DEAD || + status == SERVER_GRACEFUL); /* We consider a starting server as idle because we started it * at least a cycle ago, and if it still hasn't finished starting @@ -1070,13 +1076,28 @@ static void perform_idle_server_maintenance(void) ++idle_thread_count; } } - /* XXX any_dead_threads may not be needed any more GLA */ - if (any_dead_threads && free_length < idle_spawn_rate + if (any_dead_threads && totally_free_length < idle_spawn_rate && (!ps->pid /* no process in the slot */ || ps->quiescing)) { /* or at least one is going away */ + if (all_dead_threads) { + /* great! we prefer these, because the new process can + * start more threads sooner. So prioritize this slot + * by putting it ahead of any slots with active threads. + * + * first, make room by moving a slot that's potentially still + * in use to the end of the array + */ + free_slots[free_length] = free_slots[totally_free_length]; + free_slots[totally_free_length++] = i; + } + else { + /* slot is still in use - back of the bus + */ free_slots[free_length] = i; + } ++free_length; } + /* XXX if (!ps->quiescing) is probably more reliable GLA */ if (!any_dying_threads) { last_non_dead = i; ++total_non_dead; @@ -1107,7 +1128,9 @@ static void perform_idle_server_maintenance(void) idle_spawn_rate = 1; } else { - + if (free_length > idle_spawn_rate) { + free_length = idle_spawn_rate; + } if (idle_spawn_rate >= 8) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, ap_server_conf, "server seems busy, (you may need "