After my WAMP days were over I declare that I shall no longer fall victim to an inefficient/unoptimized lifestyle. So here is my home brew optimization tutorial (yes, I really did it myself this time!).

Preface

Before you do anything, I recommend you add the following lines of code into footer.php of your WordPress blog:

<?phpecho get_num_queries();?> queries
<?php timer_stop(1);?> seconds

This will tell you the number of MySQL queries called and the number of seconds it took to generate the page you are on.

Once you’ve played a little bit with the timer_stop(1) function, you will notice that the first time generation of a page will take longer than successive tries. This is because WordPress has an internal cache mechanism built in and it is on by default. If you are happy with the page generation time then you should just ignore my tutorial. To me, I cannot stand leaving anything unoptimized because why be wasteful when you don’t have to be? Also in case your blog gets dugg, you will have the pleasure of seeing that your blog can withstand hundreds of visitors without crashing like most others.

Optimizing Apache

For the record, my blog is hosted on a dedicated 2.0GHz P4 with 1GB of DDR RAM. This information (at least the memory part) is important to figuring out how to optimize your Apache. One of the most common reasons why blogs crash is because Apache is able to run loose and spawn an infinite number of httpd threads; thus, killing the memory and the machine. We need to tell Apache to STOP when we know we have reached our physical limitation. This is easily done by modifying your Apache configs in your httpd.conf file. Here is what I added to my httpd.conf:

MaxKeepAliveRequests0KeepAliveTimeout0

KeepAlives is a feature that keeps a connection open for the duration specified by “KeepAliveTimeout”. When enabled this will alleviate the visitor of the overhead needed to create a new thread request if the next request occurs within the KeepAliveTimeout. You should turn this off because the overhead is minuscule and leaving it on will waste memory.

ServerLimit27

This setting is important because it would stop Apache from spawning too many httpd threads and fill up all the memory. Once the memory is filled up, your system will automatically start using swap space. It is VERY BAD for a web server to be served from swap space! The setting above tells apache to not spawn more than 27 httpd threads. Here are the formulas to help you find out what your server limit should be.

If you are sharing your machine with anything else (e.g. MySQL database) you should use the formula below:

MaxClients = Total RAM / (2 * Apache Process Memory Size)

If you are using your machine solely for Apache you should use the following formula:

MaxClients = Total RAM / Apache Process Memory Size

My RAM is 1024MB and my Apache processes are about 19MB each. I also run MySQL on the same machine so using the first formula gives me ~27.

MinSpareServers15MaxSpareServers20

These 2 settings mean just what they say. MinSpareServer specifies the minimum number of httpd threads to be left for spare usage at any given time. MaxSpareServer specifies the maximum. The trick is to adjust this to best suit your traffic. The general rule of thumb is that if Apache needs to spawn more than 4 threads at any given time then you should increase your MinSpareServers value. MaxSpareServers is used to keep spawned spare threads in check. For example, if visitors are actively using 5 of your servers, you will have 15 spare servers sitting in the background in case usage increases dramatically. When visitor usage increases to 8, Apache might increase the number of spare threads to 20. Once usage increases to 10, Apache will not spawn anymore spare threads.

MaxClients27

If you know that your machine cannot handle 100 users then you should cap it to what you think it can handle. I’ve changed my max clients to 27 (1 per httpd thread).

ListenBacklog27

This setting tells Apache to listen to the next 27 requests. If you know you cannot handle those extra requests it is better to deny the user right away instead of having them wait for a server timeout.

MaxRequestsPerChild4000

Contrary to what this looks like, this is the number of requests the child handles until it dies. With the setting above, one httpd thread will handle 4000 requests then it will die. If you keep the original setting (0, unlimited), the child process will never die and it might cause memory leakage issues later on.

After saving your httpd.conf, restart your Apache server and the changes should take effect. Now, you can move onto the next step, MySQL optimization.

[…] PHP was not as hard as I thought. Little did I know that the hardest part will come when I start optimizing the server. ids.push(49); if (!sz_post_config_params){var sz_post_config_params = new Array();} […]