A nuance of Apache's memory handling means it always appears to be eating more and more memory - top's VIRT value is often high when using prefork.c
(which I assume you are):
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
10385 apache 15 0 376m 48m 3932 R 20.3 1.2 0:01.34 httpd
10423 apache 16 0 376m 46m 4576 S 15.0 1.2 0:01.09 httpd
10153 apache 15 0 337m 61m 4672 S 11.6 1.6 0:03.94 httpd
10419 apache 15 0 383m 54m 4696 S 11.6 1.4 0:01.00 httpd
The value you want to monitor is RES - this is the size of the greatest amount of memory that child thread has consumed (in my case, PHP is run as part of that thread, hence the "bloat" as libraries and data are loaded). The thread does not release the allocated memory, however when the apache process kills the thread after its maxrequests as per
<IfModule prefork.c>
MaxRequestsPerChild 1000
the thread will return to its native memory consumption. This is the same effect as restarting apache, although a restart involves a temporary loss of service (nothing is listening on port 80) whereas MaxRequestsPerChild only controls child threads, ensuring that there is still a service listening on port 80 (or wherever it's configured to listen).
To lower apache's total memory usage, ensure you are only loading the apache modules you require, and monitor apache's threads while you run a very large PHP script (ini_set('memory_limit', '128M');
then recursively load data into an array - that should do it). Then, during real world usage, lower the MaxRequestsPerChild
value until you see your apache RES
at a reasonable level. Don't forget this is only lowering the possibility of a child thread running a large script at the beginning of its "life" (the more children that do this, the more total memory apache uses),
Here are some useful parameter tuning articles: