When the system is started, all memory pages are available for use by
the programs (processes). Unless a program is really small (in which
case at any one time the entire program will be in memory), the
process running this program uses only a few segments of the program,
each segment mapped onto its own memory page. Therefore, only a few
memory pages are needed—generally fewer than the
program's size might imply.
When a process needs an additional program segment to be loaded into
memory, it asks the system whether the page containing this segment
is already loaded. If the page is not found, an event known as a
"page fault" occurs. This requires
the system to allocate a free memory page, go to the disk, and
finally read and load the requested segment into the allocated memory
page.
If a process needs to bring a new page into physical memory and there
are no free physical pages available, the operating system must make
room for this page by discarding another page from physical memory.
If the page to be discarded from physical memory came from a binary
image or data file and has not been modified, the page does not need
to be saved. Instead, it can be discarded, and if the process needs
that page again it can be brought back into memory from the image or
data file.
However, if the page has been modified, the operating system must
preserve the contents of that page so that it can be accessed at a
later time. This type of page is known as a dirty
page, and when it is removed from memory it is saved in a
special sort of file called the swap file. This
process is referred to as swapping out.
Accesses to the swap file are very slow compared with the speed of
the processor and physical memory, and the operating system must
juggle the need to write pages to disk with the need to retain them
in memory to be used again.
To try to reduce the probability that a page will be needed just
after it has been swapped out, the system may use the LRU (least
recently used) algorithm or some similar algorithm.
To summarize the two swapping scenarios, discarding read-only pages
incurs little overhead compared with discarding data pages that have
been modified, since in the latter case the pages have to be written
to a swap partition located on the (very slow) disk. Thus, the fewer
memory pages there are that can become dirty, the better will be the
machine's overall performance.
But in Perl, both the program code and the program data are seen as
data pages by the OS. Both are mapped to the same memory pages.
Therefore, a big chunk of Perl code can become dirty when its
variables are modified, and when those pages need to be discarded
they have to be written to the swap partition.
This leads us to two important conclusions about swapping and Perl:
-
Running the system when there is no free physical memory available
hinders performance, because processes' memory pages
will be discarded and then reread from disk again and again.
-
Since the majority of the running code is Perl code, in addition to
the overhead of reading in the previously discarded pages, there is
the additional overhead of saving the dirty pages to the swap
partition.
In addition, it is important to be aware that for better performance,
many programs (particularly programs written in Perl) do not return
memory pages to the operating system even when they are no longer
needed. If some of the memory is freed, it is reused when needed by
the process itself, without creating the additional overhead of
asking the system to allocate new memory pages. That is why Perl
programs tend to grow in size as they run and almost never shrink.
When the process quits, it returns all the memory pages it used to
the pool of available pages for other processes to use.
It should now be obvious that a system that runs a web server should
never swap. Of course, it is quite normal for a desktop machine to
swap, and this is often apparent because everything slows down and
sometimes the system starts freezing for short periods. On a personal
machine, the solution to swapping is simple: do not start up any new
programs for a minute, and try to close down any that are running
unnecessarily. This will allow the system to catch up with the load
and go back to using just RAM. Unfortunately, this solution cannot be
applied to a web server.
However, due to faulty code, sometimes a process might start running
in an infinite loop, consuming all the available RAM and using lots
of swap memory. In such a situation, it helps if there is a big
emergency pool (i.e., lots of swap memory). But the problem must
still be resolved as soon as possible, since the pool will not last
for long. One solution is to use the
Apache::Resource module, described in the next
section.