Here is another idea for solving the scoreboard problem....

Today, the scoreboard serves two purposes: as a place to hold and maintain child 
process status as
used by perform_idle_server_maintenance() and as a place to hold bytes used by 
mod_status.  And the
main "problem" is how to manage the storage used by the scoreboard. Here is a rough 
sketch of my
proposal:

First, seperate out the scoreboard into two pieces, one piece used by
perform_idle_server_maintenance() to maintain child processes status and the other 
piece for use by
mod_status.  The storage required for the idle_server_maintenance piece is reduced by 
an order of
magnitude.  Now we have two problems to solve:

1. How to manage new process creation when idle_server_maintenance() detects a child 
process is in
shutting down gracefully...
Basically this problem is addressed by allocating a pm_scoreboard larger (say 5x 
larger) than you
need at steady state. If you detect a process is shutting down, create a new process 
and give it a
place in the pm scoreboard. Remember, since a  pm score entry is much smaller than 
before, you can
have a lot more of them w/o using gobs of memory. Can place upper limits on the number 
of child
processes (and the number of pm score slots) but you probably will not be memory 
constrained due to
the pm score size.  This gives us a lot of wiggle room to play with algorithms for 
managing the pm
score.

2. How to maintain bytes used by mod_status?
This is a bit tricker and there are multiple possible solutions. The key is to manage 
the storage
such that entries can be selectively reused.  One possible implementation...

A pm_score entry (one per process) contains in addition, to a status field, an array 
of pointers,
each pointing to a mod_status scoreboard slot (ms_score). There is a pointer per 
thread in the child
process.

struct pm_score {
int status;
ms_score *[THREADS_PER_CHILD];
}

As threads exit, they set a field in ms_score indicating that they are done using the 
entry and that
it can be put on a free list to be reused by the parent in a new process.  In the 
event of a child
seg fault, the parent can assume ownership of all the ms_score slots and put them on 
the free list.
I think this can be done w/o requiring any locks.


>
> > Idle processing would remain largely the same. Count the number of
> > idle threads and see if it falls within the min/max range. If not,
> > consider adjusting.
> >
> > For request processing I suggest the following algorithm. First,
> > we need to add a directive config called max_total_threads. The
> > algorithm would then be:
> >      x = count_the_total_number_of_threads;
> >      y = count_the_total_number_of_servers;
> >      if (((x + threads_per_child) <= max_total_threads) &&
> >          (y < max_clients))
> >         start_a_new_server;
> >
> > This allows max_clients to be set higher, even though the number
> > of threads per child is high because you could configure something
> > like the following:
> >
> > max_clients = 250;         /* A very large scary number, but stick with me... */
> > threads_per_child = 100;   /* for a total of 25000 possible threads! */
> >
> > max_total_threads = 300;   /* Max at any given time, out of that possible 25000. */
> > min_spare_threads = 20;
> > max_spare_threads = 50;
> >
> > This means that there will be 3 servers at a minimum (* 100 threads = 300).
> > But, in the worst case, there could be as many as 201 servers running (each
> > with 1 thread still left, where  201 + 100 > 300 so no new servers can start).
> >
> > If you have 201 requests still being processed, then the server is probably
> > relatively busy (as opposed to the current design where the server is nearly
> > idle). If a server that is tuned reasonably, given its hardware
> > capabilities, gets to this busy state then it is understandable that the
> > server is slow in processing new requests.
> >
> > Thoughts?
>
> I don't see how this will work without a major overhaul of the basic
> Apache design.  The problem is the scoreboard.  Each thread/process gets a
> spot in the scoreboard, and in order for a new process to start, there
> needs to be a spot in the scoreboard for all of it's threads.  Currently,
> all of the threads for a given process are in contiguous spots in the
> scoreboard.  In order to handle the case that you are talking about, we
> will need to modify the scoreboard, to either consolidate threads in the
> scoreboard as processes exit (a nightmare for serialization), or we will
> need to make the scoreboard smarter about finding open locations in the
> scoreboard (again serialization issues).  Currently locations in the
> scoreboard are a very simple mathematical operation, this will need to
> change in order for your plan to work.
>
> The numbers you describe above will actually allocate a scoreboard big
> enough to hold 25000 threads, which is a non-starter.  You will need to
> figure out how you are going to allocate a scoreboard, without
> over-allocating too much, and without introducing a lot of serialization,
> because adding too much serialization will kill our performance.
>
> Allow me to offer another idea.  What if we create temporary process for
> this case.  The idea is that when we are shutting down, if processes get
> stuck with a couple of long-lived requests, then the parent checks the
> scoreboard to see how many contiguous locations there are in the
> scoreboard.  It then creates a single process with that many threads.  As
> more processes are required, we can create more temporary servers.  Then,
> as soon as we can create a full process, we start to kill of the temporary
> process, and spawn new full processes.
>
> This solves your problem of having processes stuck in long-lived requests,
> and it solves the scoreboard issue too.
>
> Ryan
>
> _______________________________________________________________________________
> Ryan Bloom                        [EMAIL PROTECTED]
> 406 29th St.
> San Francisco, CA 94131
> -------------------------------------------------------------------------------
>
>

Reply via email to