I used to hate WordPress (and Apache). When x5315 and I first got a cheap VPS from XenEurope (I recommend them, but don’t be as stingy as us!) it had 128MB of RAM. We both wanted WordPress blogs. Thus what ensued was a performance nightmare. For the record, we ended up using lighttpd and FastCGI instead of Apache, but most people use Apache so that’s what I’m going to focus on here.
Does your cloud server have 2GB of RAM?
Apache by default has ridiculous settings. It will try to serve 150 clients simultaneously before it starts making new clients wait. Each one of those 150 clients will be a memory guzzling Apache process that will stay alive for 15 seconds (strictly speaking only 100 will stay alive at any one time) after the client has finished and will hang around for 300 seconds before timing out if the client is slow. Not only that, but Apache will always try to keep around 10 processes spare for serving new requests.
New Apache processes serving this blog appear to take anything from 5-15MB of RAM. At worst, that means that if Apache tries to maintain 150 concurrent processes it will use over 2GB of RAM. Way more than the average VPS, cloud server, EC2 instance, whatever. When this happens, Linux will start swapping out processes to disk, and your server will basically grind to a halt. In most situations, you will struggle to even SSH in to the server.
Try it yourself
Why not try ‘sieging’
your favourite WordPress blog you think is run on a tiny EC2 instance a quick test WordPress installation from your computer (install siege, available in all good package repositories) to any sort of VPS or cloud instance (Rackspace are good, and they are faster to set something up with than Amazon EC2):
siege -c 250 http://path.to.blog/
That command tries to run 250 concurrent requests (repeatedly) against the URL. Essentially a DoS attack (that’s why you should run it on your own installation, otherwise it’s illegal!).
Like you with your test installation, most people wont have configured Apache properly. At best others may have installed some sort of caching plugin (which wont help you against Apache’s memory guzzling tendencies). Your server will fall to its knees.
So how do you fix it?
By keeping Apache on a really tight leash. Here’s the relevant lines from the Apache config running this blog:
StartServers 2 MinSpareServers 2 MaxSpareServers 6 MaxClients 10 MaxRequestsPerChild 300
- StartServers is fairly self explanatory. We’re restricting Apache to just 2.
- MinSpareServers is the number of processes Apache will try and keep around to handle incoming requests.
- MaxSpareServers is the number of processes Apache will keep around after serving requests before killing some off. It’s not hugely important what value you have this at – in fact a higher value will probably help reduce cache thrashing (no idea though)
- MaxClients is the important one. Set it to something low, here I’ve set it to 10, but if you have a hefty WordPress site (e.g. lots of plugins) you may want to set it as low as 5 on a server with only 256MB RAM for example.
- MaxRequestsPerChild is the number of clients a process can serve before it dies and a new one is created in its place. Setting this to a reasonable value makes Apache ‘refresh’ old processes which have probably consumed a lot of RAM.
Technical note: This config assumes you are using prefork MPM (the default), rather than worker threads.
For added performance, reduce the
KeepAliveTimeout to something less than 15.
With these settings, Apache will at least avoid killing your server. If your blog is getting a large number of requests (congratulations!), some readers may have to wait a few seconds or even get rejected, but that’s just the way it is, and that’s better than not being able to even SSH in to your server to fix things!
Edit: _pdeschen on Hacker News suggested that for real performance, you could try nginx. I also recommend nginx (I use it for all my other hosting) and he has a blog post about getting WordPress to work with nginx. Thanks!