Drupal Performance Tuning

Average: 3.7 (6 votes)

Since the Drupal installation was so simple, I never gave much though to any performance optimizations that could be done - other than the standard Drupal page caching and the new CSS aggregation options.  But tonight, after installing Drupal on a web hosting service that I have had for awhile and never did much with - and noticing the horrible performance (probably due to a slow network connecting the web server to the MySQL server), I decided to explore if there was anything that could be done to improve performance.

The first thing I looked at was a PHP accelerator.  After a quick search, I settled on eAccelerator. After installing it (using NetBSD's pkgsrc system - cd /usr/pkgsrc/www/php-eaccelerator && make install), I simply added the following to my php.ini file:

extension=eaccelerator.so
eaccelerator.shm_size="16"
eaccelerator.cache_dir="/tmp/eaccelerator"
eaccelerator.enable="1"
eaccelerator.optimizer="1"
eaccelerator.check_mtime="1"
eaccelerator.debug="0"
eaccelerator.filter=""
eaccelerator.shm_max="0"
eaccelerator.shm_ttl="0"
eaccelerator.shm_prune_period="0"
eaccelerator.shm_only="0"
eaccelerator.compress="1"
eaccelerator.compress_level="9"

After restarting Apache, the number of Conk front pages that could be served per second doubled from 16.95 to 36.75 pages per second, as measured with the Apache 'ab' utility (32 concurrent users).  Pretty impressive for 5 minutes of work...

My next idea was to move the MySQL database off of the web server and onto a faster machine on my network.  This server is only a 933MHz Pentium III with 512MB of RAM, and I thought that Drupal's heavy use of the database might be limiting performance.  After moving the server, the speed increased to 46.25 pages per second.  Pretty good, although the improvement might not be enough to justify making this site dependent on two servers instead of just the one. 

Then I began to google for MySQL tuning tips.  There was a lot of good information out there, but I ended up just copying someone's my.cnf file, as shown below:

[mysqld]
skip-innodb
max_connections = 500
key_buffer = 16M
myisam_sort_buffer_size = 64M
join_buffer_size = 1M
read_buffer_size = 1M
sort_buffer_size = 2M
table_cache = 1024
thread_cache_size = 64
wait_timeout = 1800
connect_timeout = 10
max_allowed_packet = 16M
max_connect_errors = 10
query_cache_limit = 1M
query_cache_size = 32M
query_cache_type = 1

[myisamchk]
key_buffer = 64M
sort_buffer = 64M
read_buffer = 16M
write_buffer = 16M

After restarting the MySQL server, the performance was 45.27 pages per second - comparable to what I was seeing with the external, faster db server.

So without any hardware changes and almost no work, I was able to greatly improve the performance of this server, as you can see in this table. 

Setup Page Requests Per Second Time Per Request
Stock Drupal 16.95 1888.03ms
eAccelerator 36.75 870.82ms
eAccelerator +
tuned MySQL
on fast external
server
46.25 691.90ms
eAccelerator +
MySQL tuning on
same server
45.27 706.82ms

Edit: This above numbers were with 32 concurrent simulated users, which is probably a little unrealistic for this site.  Using 4 concurrent users, the eAccelerator + MySQL tuning on same server times were 54.30 pages per second and 73.67ms for time per request.