Increase WordPress Performance on Apache with Worker MPM, PHP and mod_fcgid

This is a continuation of two previous posts about Apache performance running PHP-apps like WordPress. One was on running PHP via CGI and the other was on running Apache with the thread-based “Worker” MPM instead of the default “Prefork” MPM.

As mentioned in the other posts (incase you don’t want to read them… I don’t blame you, I’m a horrible writer) I’ve been running WordPress on Apache for about 4 years now. All of those years I used the easiest “out of box” experience which was Apache + prefork MPM + mod_php — this is the default setup for Apache almost anywhere I’ve seen (RimuHosting, Amazon EC2, SliceHost, VPS.net — CentOS and Debian) and the easiest to get non-PHP folks like myself from zero to a running WordPress install.

Unfortunately as the site traffic grew, performance of the sites went to the dogs. More times than not it was due to memory being exhausted and dish trashing occurring for no great reason. This includes using WordPress in conjunction with a static-page caching plugin like WP-SuperCache.

Recently, in an attempt to get away from Apache and this problem I discovered that there are two modifications to how I’m hosting WordPress that can potentially increased performance if done correctly (SPOILER: It increased performance quite a bit for me):

  • Apache “Worker” MPM: Change to using the thread-based “Worker” MPM instead of the default “Prefork” process-based MPM. Instead of the 1-process-per-connection model of Prefork, the “Worker” MPM uses a 1-process-per-thread-group-AND-1-thread-per-connection model. The “Worker” MPM tends to have lower memory requirements and can perform better on many-cored machines. In my own limited tested, this switch made quite a bit of difference for page-load times coming up “instantly” instead of slight page-load pauses I saw with “Prefork” even with idle processes sitting around.
  • Using FCGID to Run PHP: In the default Prefork+mod_php mode, Apache loads up a PHP VM inside of each server process (remember, 1 process per connection in this mode). Unfortunately this is like loading a JavaVM-per-process and you end up with Apache processes that are 40-75mb in size eating up your RAM. You can imagine if you have MaxClients set too high in Apache in this case, getting Dugg or Slashdotted will destroy your server as it tries to spin up 100+ 50MB processes. Fortunately there is a way to external PHP execution outside of the Apache process by way of theĀ php-cgi command line interpreter. At the least you can allow Apache to call out externally to php-cgi every time to process a PHP file. This shrinks your Apache process size back down to about 5MB, but you have the latency of spinning up and shutting down the PHP VM every time you call out to it. This is where mod_fcgid comes in handy; It will actually keep a specified number of external PHP processes running in the background answering requests from Apache idle and ready to go — no need to spin up or shut down PHP VMs on every request.

Implementing both of these changes on the site have taken the average page load times from an average of 11 seconds down to around 4 seconds:

I am no longer seeing the strange pauses for original connections to the site, and flipping between pages of the site (go ahead and try it now) are really fast, maybe about 1 second what I’m seeing now.

Fortunately, Michael Stucki has written a guide on exactly how to set this up (on Debian) here. The very short version of it looks something like this (for the folks skimming for config details):

1. Run ‘apt-get -u install php5-cgi libapache2-mod-fcgid apache2-mpm-worker

2. Disable the ‘php5‘ Apache mod (e.g. ‘a2dismod php5‘)

3. Enable the ‘actions‘ and ‘fcgid‘ Apache mods (e.g. ”a2enmod fcgid)

4. Edit /etc/apache2/mods-enabled/fcgid.conf and bump the “IPCCommTimeout” up to 60 from the default of 20 (TIP: Download example fcgid.conf file)

5. Create a /etc/apache2/conf.d/php-fcgid.conf file with the contents Michael specifies here. (TIP: Download example php-fcgid.conf file)

6. Create a sym link between the PHP CGI command line executable (/usr/bin/php5-cgi) and the server-accessible executable specified in the php-fcgid.conf file (/var/www/fcgi-bin.d/php5-default/php-fcgi-wrapper) – lines 23 and 30 from the example php-fcgid.conf file above specifically. Just follow Michael’s steps here.

7. Restart Apache — seriously, you are done.

I was pretty shocked how easy this all ways once I understood what I was doing. Years ago when I was new to PHP/Apache/WordPress I likely couldn’t have followed this guide, but given that I needed a solution and more of this stuff made sense to me (like running PHP via CGI), it sort of clicked.

I’ve tried to provide a higher overview of my problems and the solutions for tuning Apache & PHP so you have the context I didn’t have to make more sense of the solutions.

Happy Server’ing!

Tags: , , , , , , ,

This post was written by:

Riyad Kalla - who has written 2275 posts on The Buzz Media.

Software development, video games, writing, reading and anything shiny. I ultimately just want to provide a resource that helps people and if I can't do that, then at least make them laugh.

Contact the author

No comments yet.

Leave a Reply