I've rewritten the guide's swapping section now delving into quite
technical details. Please take a moment to review this section and comment
on it. 

I have tried to stay on focus to deliver as much as possible relevant
details without actually delving into the fine details of memory
management techniques like virtual memory, sharing and alike, therefore
this version is a simplified one. I hope that it'll be still educating and
clear for folks with no CS background. The goal is to helps to understand
the reasoning behind desired swapping prevention under mod_perl.

Submitting of the additional techniques/details and possible
problems/solutions that I've not covered or covered incorrectly is very
welcome. Remember that I'm not trying to reproduce the operating systems
course but provide only the relevant details. Thanks a lot!

So here we go:

=head2 Swapping Prevention

Before we delve into swapping process details, let's refresh our
memory management knowledge.

The computer memory is called RAM, which stands for Random Access
Memory.  Reading and writing to RAM is by a few orders faster than
doing the same operations with a hard disk, the former uses the
non-movable memory cells, while the latter uses the rotating magnetic
media.

On most operating systems a swap memory is used as an extension for
RAM and not as a duplication of it. So if your OS is one of those, if
you have 128MB of RAM and 256MB swap partition, you have a total of
384MB of memory available for OS. You should never count this extra
memory when you decide on the maximum number of processes to be run,
and we will show why in the moment.

The swapping memory can be built of a number of hard disk partitions
and swap files formatted to be used as a swap memory. When you need
more swap memory you can always extend it on demand as long as you
have some free disk space (for more information see the I<mkswap> and
I<swapon> manpages).

System memory is quantified in units called memory pages. Usually the
size of the memory page is 4KB or 8KB.  So if you have 256MB of RAM
installed on your machine and the page size is 4KB your system has
64,000 memory pages to work with. When the system is started all
memory pages are available for use by the programs (processes).

When a process asks for a specific memory page, the system checks
whether this page is already loaded in memory and if it's not, the
I<page fault> event occurs, which requires the system to allocate a
free memory page and load this page into memory.

Each program asks a system for a certain number of the RAM memory
pages when it started.  For example if a program needs 512KB of memory
when it starts and the memory page size is 4KB, the system will have
to allocate 128 memory pages for this program. Note that if some of
the pages can be shared with other processes it's possible that less
pages will be needed.  For examples pages that are occupied by all
kind of I<libc> libraries are generally shared between the processes that
use these libraries.

After the process was started it might ask the OS for additional
memory pages when it needs them. While there are memory pages
available, the OS allocates these demanded memory pages and delivers
them to the process that asks for them.  Most programs, particularly
Perl programs, on most modern OSs don't return memory pages while they
are running to improve the performance. If some of the memory gets
freed it's reused when needed by the process, without creating an
additional overhead by asking the system to allocate new memory pages.
That's why you can observe that Perl programs are usually growing in
size and almost never shrink.

When the process quits it returns its memory pages to the pool of
freely available pages for other processes to reuse.

The more processes are running the more memory pages are used, the
less available memory pages remain.  At some point when a process asks
for memory pages the system cannot find any available, since all of
them are in use. That's the moment when the system starts the swapping
process which uses the swapping memory.

When there is no free memory pages available, in order to gain the
required number of memory pages requested by the process the system
(kernel) has to page out (i.e. move to a hard disk's swap partition)
exactly the same number of pages.  The kernel pages out memory pages
using the LRU (least recently used) or a similar algorithm to decide
which pages to take out, in attempt to prevent the situation where the
next process which is going to get CPU will need exactly the pages
that were just paged out, and therefore prevent the page fault (when
the page is not found in RAM). Because if the page faults occur, more
pages will have to be swapped out in order to free the memory for the
pages that get swapped in (loaded from swap into RAM).

When the CPU has to page memory pages in and out, the system slows
down, and not serving the process as fast as before. This leads to
accumulation of the processes waiting for CPU, which causes processing
demands to go up, which in turn slows down the system even more as
more memory is required.  This ever worsening spiral will lead the
machine to halt, unless the resource demand suddenly drops down and
allows the processes to catch up with their tasks and go back to
normal memory usage.

This scenario is certainly educating, and it should be now obvious
that your system that runs the web server should never swap. It's
absolutely normal for your desktop to start swapping. You will see it
immediately since things will slow down and sometimes the system will
freeze for a short periods. But as we just mentioned, you can stop
starting new programs and can quit some, thus allowing the system to
catch up with the load and come back to use the RAM. In the case of
the web server you have much less control since it's users who load
your machine. Therefore you should configure the server, so that the
maximum number of possible processes will be small enough using the
C<MaxClients> directive. This will ensure that at the peak hours the
system won't swap. Remember that swap space is an emergency pool, not
a resource to be used routinely.  If you are low on memory and you
badly need it, buy it or reduce a number of processes to prevent
swapping.

However sometimes due to the faulty code, some process might start
spinning in some unconstrained loop, consuming all the available RAM
and starting to heavily use the swap memory. In such a situation it
helps when you have a big emergency pool (i.e. lots of swap
memory). But you have to resolve this problem as soon as possible since
this pool
won't last for a long time. In the meanwhile the C<Apache::Resource>
module can be handy.

Sometimes calling an undefined subroutine in a module can cause a
tight loop that consumes all the available memory.  Here is a way to
catch such errors.  Define an C<AUTOLOAD> subroutine:

  sub UNIVERSAL::AUTOLOAD {
    my $class = shift;
    warn "$class can't \$UNIVERSAL::AUTOLOAD!\n";
  }

This will produce a nice error in I<error_log>, giving the line number
of the call and the name of the undefined subroutine.

_____________________________________________________________________
Stas Bekman              JAm_pH     --   Just Another mod_perl Hacker
http://stason.org/       mod_perl Guide  http://perl.apache.org/guide 
mailto:[EMAIL PROTECTED]   http://perl.org     http://stason.org/TULARC
http://singlesheaven.com http://perlmonth.com http://sourcegarden.org


Reply via email to