]> granicus.if.org Git - apache/commitdiff
MPMs unix: bind the bucket number of each child to its slot number
authorYann Ylavic <ylavic@apache.org>
Tue, 12 Mar 2019 10:45:02 +0000 (10:45 +0000)
committerYann Ylavic <ylavic@apache.org>
Tue, 12 Mar 2019 10:45:02 +0000 (10:45 +0000)
We need not remember each child's bucket number in SHM for restarts, for the
lifetime of the httpd main process the bucket number can be bound to the slot
number such that: bucket = slot % num_buckets.

This both simplifies the logic and helps children maintenance per bucket in
threaded MPMs, where previously perform_idle_server_maintenance() could create
or kill children processes for the buckets it was not in charge of.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1855306 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/scoreboard.h
server/mpm/event/event.c
server/mpm/motorz/motorz.c
server/mpm/prefork/prefork.c
server/mpm/worker/worker.c

diff --git a/CHANGES b/CHANGES
index 4c2bf10c0835d4c20373978666fe5595664ae273..e50e1caff0c17d3c6d93c289eaef2b9849106698 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.5.1
 
+  *) MPMs unix: bind the bucket number of each child to its slot number, for a
+     more efficient per bucket maintenance. [Yann Ylavic]
+
   *) mod_http2: when SSL renegotiation is inhibited and a 403 ErrorDocument is
      in play, the proper HTTP/2 stream reset did not trigger with H2_ERR_HTTP_1_1_REQUIRED.
      Fixed. [Michael Kaufmann] 
index 97d8d39c4a03148cdba585b6605260ba17c53174..0d72210789492056b91dafb837e155681428fe4c 100644 (file)
@@ -148,7 +148,10 @@ struct process_score {
     apr_uint32_t lingering_close;   /* async connections in lingering close */
     apr_uint32_t keep_alive;        /* async connections in keep alive */
     apr_uint32_t suspended;         /* connections suspended by some module */
-    int bucket;             /* Listener bucket used by this child */
+    int bucket;  /* Listener bucket used by this child; this field is DEPRECATED
+                  * and no longer updated by the MPMs (i.e. always zero) from
+                  * 2.5.x and later.
+                  */
 };
 
 /* Scoreboard is now in 'local' memory, since it isn't updated once created,
index 1458a8cc80b64fff3a73398fe87cbf95bf876687..4bb2d5bd0fd09e57d5c4bf0f4af3e7301bd06a99 100644 (file)
@@ -2977,7 +2977,6 @@ static int make_child(server_rec * s, int slot, int bucket)
 
     ap_scoreboard_image->parent[slot].quiescing = 0;
     ap_scoreboard_image->parent[slot].not_accepting = 0;
-    ap_scoreboard_image->parent[slot].bucket = bucket;
     event_note_child_started(slot, pid);
     active_daemons++;
     retained->total_daemons++;
@@ -3016,6 +3015,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
          * that threads_per_child is always > 0 */
         int status = SERVER_DEAD;
         int child_threads_active = 0;
+        int bucket = i % num_buckets;
 
         if (i >= retained->max_daemons_limit &&
             free_length == retained->idle_spawn_rate[child_bucket]) {
@@ -3039,7 +3039,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
                  */
                 if (status <= SERVER_READY && !ps->quiescing && !ps->not_accepting
                     && ps->generation == retained->mpm->my_generation
-                    && ps->bucket == child_bucket)
+                    && bucket == child_bucket)
                 {
                     ++idle_thread_count;
                 }
@@ -3050,7 +3050,9 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
             last_non_dead = i;
         }
         active_thread_count += child_threads_active;
-        if (!ps->pid && free_length < retained->idle_spawn_rate[child_bucket])
+        if (!ps->pid
+                && bucket == child_bucket
+                && free_length < retained->idle_spawn_rate[child_bucket])
             free_slots[free_length++] = i;
         else if (child_threads_active == threads_per_child)
             had_healthy_child = 1;
@@ -3243,13 +3245,14 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
                 retained->total_daemons--;
                 if (processed_status == APEXIT_CHILDSICK) {
                     /* resource shortage, minimize the fork rate */
-                    retained->idle_spawn_rate[ps->bucket] = 1;
+                    retained->idle_spawn_rate[child_slot % num_buckets] = 1;
                 }
                 else if (remaining_children_to_start) {
                     /* we're still doing a 1-for-1 replacement of dead
                      * children with new children
                      */
-                    make_child(ap_server_conf, child_slot, ps->bucket);
+                    make_child(ap_server_conf, child_slot,
+                               child_slot % num_buckets);
                     --remaining_children_to_start;
                 }
             }
index fe31e147a92150181963b0e9b33a1455383c0a94..7fd943059115f7f15aa53c72c5d619ba72a91739 100644 (file)
@@ -948,8 +948,9 @@ static void child_main(motorz_core_t *mz, int child_num_arg, int child_bucket)
     clean_child_exit(0);
 }
 
-static int make_child(motorz_core_t *mz, server_rec *s, int slot, int bucket)
+static int make_child(motorz_core_t *mz, server_rec *s, int slot)
 {
+    int bucket = slot % mz->mpm->num_buckets;
     int pid;
 
     if (slot + 1 > mz->max_daemons_limit) {
@@ -1020,7 +1021,6 @@ static int make_child(motorz_core_t *mz, server_rec *s, int slot, int bucket)
         child_main(mz, slot, bucket);
     }
 
-    ap_scoreboard_image->parent[slot].bucket = bucket;
     motorz_note_child_started(mz, slot, pid);
 
     return 0;
@@ -1036,7 +1036,7 @@ static void startup_children(motorz_core_t *mz, int number_to_start)
         if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
             continue;
         }
-        if (make_child(mz, ap_server_conf, i, i % mz->mpm->num_buckets) < 0) {
+        if (make_child(mz, ap_server_conf, i) < 0) {
             break;
         }
         --number_to_start;
@@ -1045,8 +1045,6 @@ static void startup_children(motorz_core_t *mz, int number_to_start)
 
 static void perform_idle_server_maintenance(motorz_core_t *mz, apr_pool_t *p)
 {
-    static int bucket_make_child_record = -1;
-    static int bucket_kill_child_record = -1;
     int free_length;
     int free_slots[1];
 
@@ -1070,6 +1068,7 @@ static void perform_idle_server_maintenance(motorz_core_t *mz, apr_pool_t *p)
         }
     }
     if (active > ap_num_kids) {
+        static int bucket_kill_child_record = -1;
         /* kill off one child... we use the pod because that'll cause it to
          * shut down gracefully, in case it happened to pick up a request
          * while we were counting
@@ -1078,10 +1077,7 @@ static void perform_idle_server_maintenance(motorz_core_t *mz, apr_pool_t *p)
         ap_mpm_pod_signal(all_buckets[bucket_kill_child_record].pod);
     }
     else if (active < ap_num_kids) {
-        bucket_make_child_record++;
-        bucket_make_child_record %= mz->mpm->num_buckets;
-        make_child(mz, ap_server_conf, free_slots[0],
-                   bucket_make_child_record);
+        make_child(mz, ap_server_conf, free_slots[0]);
     }
 }
 
@@ -1113,7 +1109,7 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
 
     if (one_process) {
         AP_MONCONTROL(1);
-        make_child(mz, ap_server_conf, 0, 0);
+        make_child(mz, ap_server_conf, 0);
         /* NOTREACHED */
         ap_assert(0);
         return !OK;
@@ -1201,8 +1197,7 @@ static int motorz_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
                     /* we're still doing a 1-for-1 replacement of dead
                      * children with new children
                      */
-                    make_child(mz, ap_server_conf, child_slot,
-                               ap_get_scoreboard_process(child_slot)->bucket);
+                    make_child(mz, ap_server_conf, child_slot);
                     --remaining_children_to_start;
                 }
 #if APR_HAS_OTHER_CHILD
index 78e64ab64daf2887adf6d0dcee7f215b1328c037..36577fda783aa0e33499b5671132f8db74184702 100644 (file)
@@ -643,8 +643,9 @@ static void child_main(int child_num_arg, int child_bucket)
 }
 
 
-static int make_child(server_rec *s, int slot, int bucket)
+static int make_child(server_rec *s, int slot)
 {
+    int bucket = slot % retained->mpm->num_buckets;
     int pid;
 
     if (slot + 1 > retained->max_daemons_limit) {
@@ -722,7 +723,6 @@ static int make_child(server_rec *s, int slot, int bucket)
         child_main(slot, bucket);
     }
 
-    ap_scoreboard_image->parent[slot].bucket = bucket;
     prefork_note_child_started(slot, pid);
 
     return 0;
@@ -738,7 +738,7 @@ static void startup_children(int number_to_start)
         if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
             continue;
         }
-        if (make_child(ap_server_conf, i, i % retained->mpm->num_buckets) < 0) {
+        if (make_child(ap_server_conf, i) < 0) {
             break;
         }
         --number_to_start;
@@ -747,8 +747,6 @@ static void startup_children(int number_to_start)
 
 static void perform_idle_server_maintenance(apr_pool_t *p)
 {
-    static int bucket_make_child_record = -1;
-    static int bucket_kill_child_record = -1;
     int i;
     int idle_count;
     worker_score *ws;
@@ -795,6 +793,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
     }
     retained->max_daemons_limit = last_non_dead + 1;
     if (idle_count > ap_daemons_max_free) {
+        static int bucket_kill_child_record = -1;
         /* kill off one child... we use the pod because that'll cause it to
          * shut down gracefully, in case it happened to pick up a request
          * while we were counting
@@ -825,10 +824,7 @@ static void perform_idle_server_maintenance(apr_pool_t *p)
                     idle_count, total_non_dead);
             }
             for (i = 0; i < free_length; ++i) {
-                bucket_make_child_record++;
-                bucket_make_child_record %= retained->mpm->num_buckets;
-                make_child(ap_server_conf, free_slots[i],
-                           bucket_make_child_record);
+                make_child(ap_server_conf, free_slots[i]);
             }
             /* the next time around we want to spawn twice as many if this
              * wasn't good enough, but not if we've just done a graceful
@@ -873,7 +869,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
 
     if (one_process) {
         AP_MONCONTROL(1);
-        make_child(ap_server_conf, 0, 0);
+        make_child(ap_server_conf, 0);
         /* NOTREACHED */
         ap_assert(0);
         return !OK;
@@ -982,8 +978,7 @@ static int prefork_run(apr_pool_t *_pconf, apr_pool_t *plog, server_rec *s)
                     /* we're still doing a 1-for-1 replacement of dead
                      * children with new children
                      */
-                    make_child(ap_server_conf, child_slot,
-                               ap_get_scoreboard_process(child_slot)->bucket);
+                    make_child(ap_server_conf, child_slot);
                     --remaining_children_to_start;
                 }
 #if APR_HAS_OTHER_CHILD
index 26fc324262f4f56737dd580e2ebb25b84b3bb8b6..b977e5a23da1f3545843fd761124a67f3de038ae 100644 (file)
@@ -1344,7 +1344,6 @@ static int make_child(server_rec *s, int slot, int bucket)
         worker_note_child_lost_slot(slot, pid);
     }
     ap_scoreboard_image->parent[slot].quiescing = 0;
-    ap_scoreboard_image->parent[slot].bucket = bucket;
     worker_note_child_started(slot, pid);
     return 0;
 }
@@ -1393,6 +1392,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
         int any_dead_threads = 0;
         int all_dead_threads = 1;
         int child_threads_active = 0;
+        int bucket = i % num_buckets;
 
         if (i >= retained->max_daemons_limit &&
             totally_free_length == retained->idle_spawn_rate[child_bucket]) {
@@ -1425,7 +1425,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
                 if (status <= SERVER_READY &&
                         !ps->quiescing &&
                         ps->generation == retained->mpm->my_generation &&
-                        ps->bucket == child_bucket) {
+                        bucket == child_bucket) {
                     ++idle_thread_count;
                 }
                 if (status >= SERVER_READY && status < SERVER_GRACEFUL) {
@@ -1435,6 +1435,7 @@ static void perform_idle_server_maintenance(int child_bucket, int num_buckets)
         }
         active_thread_count += child_threads_active;
         if (any_dead_threads
+                && bucket == child_bucket
                 && totally_free_length < retained->idle_spawn_rate[child_bucket]
                 && free_length < MAX_SPAWN_RATE / num_buckets
                 && (!ps->pid               /* no process in the slot */
@@ -1620,14 +1621,15 @@ static void server_main_loop(int remaining_children_to_start, int num_buckets)
                 ps->quiescing = 0;
                 if (processed_status == APEXIT_CHILDSICK) {
                     /* resource shortage, minimize the fork rate */
-                    retained->idle_spawn_rate[ps->bucket] = 1;
+                    retained->idle_spawn_rate[child_slot % num_buckets] = 1;
                 }
                 else if (remaining_children_to_start
                     && child_slot < ap_daemons_limit) {
                     /* we're still doing a 1-for-1 replacement of dead
                      * children with new children
                      */
-                    make_child(ap_server_conf, child_slot, ps->bucket);
+                    make_child(ap_server_conf, child_slot,
+                               child_slot % num_buckets);
                     --remaining_children_to_start;
                 }
             }