I was reading a post by Donncha recently on the new Wordpress plugin, WP Super Cache. He mentioned that he did not know what the performance would be like, which got me thinking about running my own tests to see for myself (I was doing some basic ones anyhow for another idea I had). There are many bloggers using Wordpress whom do not know one technical thing (nor should they!), but they should know what its gonna be like for them when their site gets busy.
N.B. My intention here was to just see what would happen. This should not be regarded as a complete proper test, but rather an indicative one. I had limited time and was not arsed doing this 100% correctly.
Hardware & OS
For the test platform I am using a 1U DELL SC1425 with 4GB RAM and 80GB 7200RPM SATA drives from Western Digital. It has two Intel GE Nics, however as I used a Cisco 3550 between the server and the load client all this took place at 100Mbps instead.
The OS is Novell Suse Linux Enterprise Server 10 SP1 (2.6.16.46-0.12-bigsmp). The only services running are;
- Apache – 2.2.3
- MySQL – Version 5.0.26
- SSHD
Configure Apache
The vanilla Apache that comes with SLES was going to be used for this test. However I would need to tweak its configuration a little so that it could cope. In order to do this, you will need to edit /etc/apache2/server-tuning.conf. Apache tuning is something of a black art. There are many factors that need to be taken into consideration. As I did not have too much time to do this, I decided to settle on this config which should be more than reasonable;
‹IfModule prefork.c› StartServers 100 MinSpareServers 10 MaxSpareServers 10 ServerLimit 10000 MaxClients 10000 MaxRequestsPerChild 2500 ListenBacklog 1000 ‹/IfModule›
I am sure someone will correct me on the above config, but remember you are going to have to customize your Apache configuration based upon your hardware set-up.
You also need to pay attention to the Apache modules that are loaded. As a rule of thumb, if you are not going to need it don’t load it. I also disabled KeepAlive and minimized the amount of logging done by Apache to the minimum. Lots of this can be customised by taking a lot at /etc/sysconfig/apache2
Configure MySQL
Normally, if I’m running MySQL for a site, it sits on its own dedicated server. However as I don’t have a spare machine for this quick test and the fact that most Wordpress instances run on the same server as the DB server, I decided to try it like that.
For this scenario we should not have to worry too much about mysql as everything should be cached.However my mysqld options in my.cnf were;
[mysqld] port = 3306 socket = /var/lib/mysql/mysql.sock skip-locking key_buffer = 16M max_allowed_packet = 1M table_cache = 64 sort_buffer_size = 512K net_buffer_length = 8K read_buffer_size = 256K read_rnd_buffer_size = 512K myisam_sort_buffer_size = 8M back_log = 100 max_connections = 1500 max_connect_errors = 150 log_slow_queries server-id = 1
Other Configs
Alas I did not have time to set up a proper monitor on the server so instead I installed Munin and scheduled a cron job to run every minute to collect server, MySQL and Apache stats. In reality you should set up some type of SNMP monitoring or use something other than Siege that has a monitor built into it (Funkbox maybe…)
You also have to install Wordpress and the WP-Super-Cache plugin, after all, that’s what we are interested in isn’t it?
When installing Wordpress, instead of using localhost as the hostname for your database, use a socket instead. This is going to give you a bit more on the performance side of things with the database (Although no doubt the DB will still be a bottle neck at some stage in your use of it)
If you already have Wordpress installed on your server, open up wp-config.php and change the DB_HOST constant to be something like below (Remember to actually check the path to your MySQL socket!)
define('DB_HOST', 'localhost:/var/lib/mysql/mysql.sock');
The Test
The first thing you have to do is to make a new post. I made a simple post with 5 Lorem Ipsum paragraphs. I then saved this as a normal html file and to my server root. This page would be my control. If WP-Super-Cache was going to perform as well as I thought, it should perform close to this.
Each test is going to run for 60 minuets at a time, so as to simulate as much as possible a rapid increase in traffic to a server (/. effect). However here I ran into a problem. I could only run siege with about 350 concurrent users. This while smaller than I thought I could do with (was hoping for 1000 but I need to get more RAM for my desktop) still should be enough to be able to form an opinion at the end of the tests.
The command to run siege with is
siege -b -c380 -t60M http://192.168.14.30/wordpress-test.html
The -b tells Siege that we are benchmarking, the -c380 is the number of concurrent users, -t60M tells siege to run for 60 minutes and finally the URL of the first test page. You’ll notice I used an IP address as I did not want to incur any time for DNS lookups.
While the first test is running, its important you don’t do anything with the server you are benchmarking against. That means, don’t be tempted to go and take a look at the pretty Munin graphs. Got have a smoke and a cup of tea and come back in half an hour.
Test One – Apache Serving a static file.
A page similar to the one to be used later was used. Siege was run with the following parameters;
siege -b -c350 -t60M http://192.168.14.30/wordpress-test.html › apache-static-test.csv
After 60 minuets the results from Siege were;
Result
** SIEGE 2.66 ** Preparing 350 concurrent users for battle. The server is now under siege...Lifting the server siege.. done. Transactions: 4773830 hits Availability: 100.00 % Elapsed time: 3599.89 secs Data transferred: 33334.71 MB Response time: 0.26 secs Transaction rate: 1326.10 trans/sec Throughput: 9.26 MB/sec Concurrency: 349.91 Successful transactions: 4773830 Failed transactions: 0 Longest transaction: 10.05 Shortest transaction: 0.00
Notes
Server load was low and consistent during this test.
Test Two – Apache serving a WP-Super-Cache file
This page was cached using the WP-Super-Cache plugin. Siege was called with the following parameters;
siege -b -c350 -t60M http://192.168.14.30/wordpress/index.php/2007/11/28/lorem-ipsum/ › apache-wpcache-test.csv
Result
** SIEGE 2.66 ** Preparing 350 concurrent users for battle. The server is now under siege...Lifting the server siege.. done. Transactions: 629905 hits Availability: 96.94 % Elapsed time: 3599.80 secs Data transferred: 1969.17 MB Response time: 1.02 secs Transaction rate: 174.98 trans/sec Throughput: 0.55 MB/sec Concurrency: 178.62 Successful transactions: 629905 Failed transactions: 19887 Longest transaction: 49.70 Shortest transaction: 0.00
Notes
Server was practically useless. Did not respond to uptime command from local or remote console. Munin monitoring died during test as previous cron requests could not complete. Server Load Reached this towards the end of the siege;
11:20pm up 2:26, 1 user, load average: 1013.09, 623.86, 960.95
The system took a further 15 min to return to a state where a reboot command could be successfully executed.
Test Three – Apache serving a WP-Super-Cache file with Op-code cache/accelerator enabled
The same page as in test two was used. eAccelerator op-code cache/accelerator was enabled.
Siege was called with the following parameters;
siege -b -c350 -t60M http://192.168.14.30/wordpress/index.php/2007/11/28/lorem-ipsum/ › apache-wpcache-opcode-test.csv
Result
Lifting the server siege.. done. Transactions: 3154641 hits Availability: 100.00 % Elapsed time: 3600.52 secs Data transferred: 9781.33 MB Response time: 0.40 secs Transaction rate: 876.16 trans/sec Throughput: 2.72 MB/sec Concurrency: 347.94 Successful transactions: 3111125 Failed transactions: 146 Longest transaction: 35.25 Shortest transaction: 0.00
Notes
Munin could complete its assigned cron tasks. Server load did still go extremely high, howerver it did respond to commands, I was able to ssh in, and it returned to normal quite quickly.
Pretty Pictures
As I said I used Munin to graph everything.

You can see where in test two everything began to die and get really crappy for me. The final peak is the op-code test (test three) and its quite respectable.

You can also see here where crazy loads appeared.

Finally memory usage throughout the tests. Look how the op-code cache really helps (hint its the smaller green peak on the right)
So what happened
As you can see in test one, a single server can handle quite a load on its own once you have it configured just a little and its serving a static file. 1326.10 Transactions a second is quite impressive.
In my second test, the requests were handled gallantly, however they are well below what our control in test one could do. The server also became quite useless, so in real life you’d be either waiting till the load subsided, or asking your host to power it down hard.
In my final test, I was much happier. I was a hell of a lot closer to my control targets and what’s more, I could access my server to issue commands. This may give me enough time to upload a complete static version of the file or kill the service or do something to help improve the situation
Great, but what does this mean
This means if you are intending on posting something that is going to get a lot of attention, and you only have one host, your site will die if you do not use caching and an op-code cache.
Be smart about things. Get a host with plenty of RAM. Use a MySQL socket instead of blindly connecting to localhost.
Spend a few days testing and tweaking Apache if you can, to get every ounce out of it.
Use an op-code cache, if really will save your ass in the long run.
Use a cache such as wp-super-cache to help alleviate the problem. Have it ready on standby so as soon as you notice the spike in traffic, you can add popular pages quickly.
What’s Next
Well if I get some more time, it will have to be lighthttpd’s turn











Comments