dgaudet     97/07/23 21:32:32

  Modified:    src       CHANGES http_main.c mod_status.c scoreboard.h
  Log:
  Exponential spawning, and a child_main optimization for single socket
  servers.
  
  Revision  Changes    Path
  1.362     +10 -0     apache/src/CHANGES
  
  Index: CHANGES
  ===================================================================
  RCS file: /export/home/cvs/apache/src/CHANGES,v
  retrieving revision 1.361
  retrieving revision 1.362
  diff -u -r1.361 -r1.362
  --- CHANGES   1997/07/24 04:23:55     1.361
  +++ CHANGES   1997/07/24 04:32:27     1.362
  @@ -1,5 +1,15 @@
   Changes with Apache 1.3a2
   
  +  *) child_main avoids an uneeded call to select() when there is only one
  +     listening socket.  [Dean Gaudet]
  +
  +  *) In the event that the server is starved for idle servers it will
  +     spawn 1, then 2, then 4, ..., then 32 servers each second,
  +     doubling each second.  It'll also give a warning in the errorlog
  +     since the most common reason for this is a poor StartServers
  +     setting.  The define MAX_SPAWN_RATE can be used to raise/lower
  +     the maximum.  [Dean Gaudet]
  +
     *) "nph-" CGIs were not compatible with HTTP/1.1 or SSL support because
        they were passed a socket that connected directly to the client.
        As such they would have to implement the transport level details
  
  
  
  1.186     +82 -34    apache/src/http_main.c
  
  Index: http_main.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/http_main.c,v
  retrieving revision 1.185
  retrieving revision 1.186
  diff -u -r1.185 -r1.186
  --- http_main.c       1997/07/22 23:51:58     1.185
  +++ http_main.c       1997/07/24 04:32:28     1.186
  @@ -1094,7 +1094,7 @@
       
       sync_scoreboard_image();
       new_score_rec = scoreboard_image->servers[child_num];
  -    new_score_rec.pid = getpid();
  +    new_score_rec.x.pid = getpid();
       old_status = new_score_rec.status;
       new_score_rec.status = status;
   
  @@ -1219,7 +1219,7 @@
       int i;
   
       for (i = 0; i < max_daemons_limit; ++i)
  -     if (scoreboard_image->servers[i].pid == pid)
  +     if (scoreboard_image->servers[i].x.pid == pid)
            return i;
   
       return -1;
  @@ -1233,7 +1233,7 @@
   
       sync_scoreboard_image();
       for (i = 0; i < max_daemons_limit; ++i) {
  -     int pid = scoreboard_image->servers[i].pid;
  +     int pid = scoreboard_image->servers[i].x.pid;
   
        if (pid != my_pid && pid != 0) { 
            int waitret = 0,
  @@ -1304,7 +1304,7 @@
   
       for (n = 0; n < max_daemons_limit; ++n) {
        if (scoreboard_image->servers[n].status != SERVER_DEAD
  -             && waitpid (scoreboard_image->servers[n].pid, &status, WNOHANG)
  +             && waitpid (scoreboard_image->servers[n].x.pid, &status, 
WNOHANG)
                    == -1
                && errno == ECHILD) {
            sync_scoreboard_image ();
  @@ -1337,7 +1337,7 @@
               if(scoreboard_image->servers[pi].status != SERVER_DEAD)
               {
                   e[hi] = pi;
  -                h[hi++] = (HANDLE)scoreboard_image->servers[pi].pid;
  +                h[hi++] = (HANDLE)scoreboard_image->servers[pi].x.pid;
               }
   
           }
  @@ -1347,9 +1347,9 @@
               if(rv == -1)
                   err = GetLastError();
               if((WAIT_OBJECT_0 <= (unsigned int)rv) && ((unsigned int)rv < 
(WAIT_OBJECT_0 + hi)))
  -                return(scoreboard_image->servers[e[rv - WAIT_OBJECT_0]].pid);
  +                return(scoreboard_image->servers[e[rv - 
WAIT_OBJECT_0]].x.pid);
               else if((WAIT_ABANDONED_0 <= (unsigned int)rv) && ((unsigned 
int)rv < (WAIT_ABANDONED_0 + hi)))
  -                return(scoreboard_image->servers[e[rv - 
WAIT_ABANDONED_0]].pid);
  +                return(scoreboard_image->servers[e[rv - 
WAIT_ABANDONED_0]].x.pid);
   
           }
       }
  @@ -2129,7 +2129,6 @@
   #endif    
   
       while (1) {
  -     int errsave;
        BUFF *conn_io;
        request_rec *r;
         
  @@ -2169,24 +2168,24 @@
           accept_mutex_on();  /* Lock around "accept", if necessary */
   
           for (;;) {
  -            memcpy(&main_fds, &listenfds, sizeof(fd_set));
  -            srv = ap_select(listenmaxfd+1, &main_fds, NULL, NULL, NULL);
  -            errsave = errno;
  -
  -            sync_scoreboard_image();
  -            if (scoreboard_image->global.exit_generation >= generation)
  -                exit(0);
  -
  -            errno = errsave;
  -            if (srv < 0 && errno != EINTR)
  -                log_unixerr("select", "(listen)", NULL, server_conf);
  -
  -            if (srv <= 0)
  -                continue;
  -
  -         lr = find_ready_listener(&main_fds);
  -         if (lr == NULL) continue;
  -         sd = lr->fd;
  +         if (listeners->next != listeners) {
  +             /* more than one socket */
  +             memcpy(&main_fds, &listenfds, sizeof(fd_set));
  +             srv = ap_select(listenmaxfd+1, &main_fds, NULL, NULL, NULL);
  +
  +             if (srv < 0 && errno != EINTR)
  +                 log_unixerr("select", "(listen)", NULL, server_conf);
  +
  +             if (srv <= 0)
  +                 continue;
  +
  +             lr = find_ready_listener(&main_fds);
  +             if (lr == NULL) continue;
  +             sd = lr->fd;
  +         } else {
  +             /* there's only one socket, just pretend we the other stuff */
  +             sd = listeners->fd;
  +         }
   
            /* if we accept() something we don't want to die, so we have to
             * defer the exit
  @@ -2223,6 +2222,12 @@
                /* ok maybe not, see ya later */
                exit (0);
            }
  +         /* or maybe we missed a signal, you never know on systems
  +          * without reliable signals
  +          */
  +         sync_scoreboard_image();
  +         if (scoreboard_image->global.exit_generation >= generation)
  +             exit(0);
           }
   
           accept_mutex_off(); /* unlock after "accept" */
  @@ -2404,7 +2409,7 @@
        * to the same word.)
        * XXX: this needs to be sync'd to disk in the non shared memory stuff
        */
  -    scoreboard_image->servers[slot].pid = pid;
  +    scoreboard_image->servers[slot].x.pid = pid;
   
       return 0;
   }
  @@ -2427,16 +2432,34 @@
   }
   
   
  +/*
  + * idle_spawn_rate is the number of children that will be spawned on the
  + * next maintenance cycle if there aren't enough idle servers.  It is
  + * doubled up to MAX_SPAWN_RATE, and reset only when a cycle goes by
  + * without the need to spawn.
  + */
  +static int idle_spawn_rate = 1;
  +#ifndef MAX_SPAWN_RATE
  +#define MAX_SPAWN_RATE       (32)
  +#endif
  +
   static void perform_idle_server_maintenance (void)
   {
       int i;
       int to_kill;
  -    int free_slot;
       int idle_count;
  +    int free_head;
  +    int *free_ptr;
  +    int free_length;
  +
  +    /* initialize the free_list */
  +    free_head = -1;
  +    free_ptr = &free_head;
  +    free_length = 0;
   
  -    free_slot = -1;
       to_kill = -1;
       idle_count = 0;
  +
       sync_scoreboard_image ();
       for (i = 0; i < daemons_limit; ++i) {
        switch (scoreboard_image->servers[i].status) {
  @@ -2452,8 +2475,10 @@
            break;
        case SERVER_DEAD:
            /* try to keep children numbers as low as possible */
  -         if (free_slot == -1) {
  -             free_slot = i;
  +         if (free_length < idle_spawn_rate) {
  +             *free_ptr = i;
  +             free_ptr = &scoreboard_image->servers[i].x.free_list;
  +             ++free_length;
            }
            break;
        }
  @@ -2463,9 +2488,12 @@
         * shut down gracefully, in case it happened to pick up a request
         * while we were counting
         */
  -     kill (scoreboard_image->servers[to_kill].pid, SIGUSR1);
  +     kill (scoreboard_image->servers[to_kill].x.pid, SIGUSR1);
  +     idle_spawn_rate = 1;
       } else if (idle_count < daemons_min_free) {
  -     if (free_slot == -1) {
  +     /* terminate the free list */
  +     *free_ptr = -1;
  +     if (free_head == -1) {
            /* only report this condition once */
            static int reported = 0;
   
  @@ -2476,8 +2504,28 @@
                reported = 1;
            }
        } else {
  -         make_child (server_conf, free_slot);
  +         if (idle_spawn_rate >= 4) {
  +             log_printf (server_conf,
  +                 "server seems busy, spawning %d children (you may need "
  +                 "to increase StartServers, or Min/MaxSpareServers)",
  +                 idle_spawn_rate);
  +         }
  +         i = 0;
  +         while (i < idle_spawn_rate && free_head != -1) {
  +             int slot = free_head;
  +             free_head = scoreboard_image->servers[free_head].x.free_list;
  +             make_child (server_conf, slot);
  +             ++i;
  +         }
  +         /* the next time around we want to spawn twice as many if this
  +          * wasn't good enough
  +          */
  +         if (idle_spawn_rate < MAX_SPAWN_RATE) {
  +             idle_spawn_rate *= 2;
  +         }
        }
  +    } else {
  +     idle_spawn_rate = 1;
       }
   }
   
  
  
  
  1.54      +2 -2      apache/src/mod_status.c
  
  Index: mod_status.c
  ===================================================================
  RCS file: /export/home/cvs/apache/src/mod_status.c,v
  retrieving revision 1.53
  retrieving revision 1.54
  diff -u -r1.53 -r1.54
  --- mod_status.c      1997/07/17 22:27:41     1.53
  +++ mod_status.c      1997/07/24 04:32:29     1.54
  @@ -472,7 +472,7 @@
                         i,(int)conn_lres,my_lres,lres);
                    else
                        rprintf(r,"<b>Server %d</b> (%d): %d|%lu|%lu [",
  -                      i,(int)score_record.pid,(int)conn_lres,my_lres,lres);
  +                      i,(int)score_record.x.pid,(int)conn_lres,my_lres,lres);
   
                    switch (score_record.status)
                    {
  @@ -537,7 +537,7 @@
                         i,(int)conn_lres,my_lres,lres);
                    else
                        rprintf(r,"<tr><td><b>%d</b><td>%d<td>%d/%lu/%lu",
  -                      i,(int)score_record.pid,(int)conn_lres,my_lres,lres);
  +                      i,(int)score_record.x.pid,(int)conn_lres,my_lres,lres);
   
                    switch (score_record.status)
                    {
  
  
  
  1.27      +5 -2      apache/src/scoreboard.h
  
  Index: scoreboard.h
  ===================================================================
  RCS file: /export/home/cvs/apache/src/scoreboard.h,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- scoreboard.h      1997/07/21 05:53:51     1.26
  +++ scoreboard.h      1997/07/24 04:32:30     1.27
  @@ -76,8 +76,11 @@
   #define SERVER_GRACEFUL 8    /* server is gracefully finishing request */
   
   typedef struct {
  -    pid_t pid;
  -    char status;
  +    union {
  +     pid_t pid;              /* if it's not DEAD then this is the pid */
  +     int free_list;          /* otherwise this is scratch space */
  +    } x;
  +    int status;
   #if defined(STATUS)
       unsigned long access_count;
       unsigned long bytes_served;
  
  
  

Reply via email to