Networking

Unix and Linux network configuration. Multiple network interfaces. Bridged NICs. High-availability network configurations.

Applications

Reviews of latest Unix and Linux software. Helpful tips for application support admins. Automating application support.

Data

Disk partitioning, filesystems, directories, and files. Volume management, logical volumes, HA filesystems. Backups and disaster recovery.

Monitoring

Distributed server monitoring. Server performance and capacity planning. Monitoring applications, network status and user activity.

Commands & Shells

Cool Unix shell commands and options. Command-line tools and application. Things every Unix sysadmin needs to know.

Home » Commands & Shells, WordPress

Improving WordPress Performance

Submitted by on May 4, 2008 – 12:39 pm 8 Comments

WordPress is a great blogging engine and decent CMS. Unfortunately, most available WordPress themes- even those claiming to be “minimalist” – are bloated and slow to load. Heavy CSS stylesheets, multiple Java scripts, numerous graphics files – all of these elements are relatively small in size, but there are many of them.

About 80% of the load time of a typical WordPress page is spent on HTTP queries – not on downloading the actual content. You browser will query the server 30-50 or more times when loading a WordPress page. There is a latency associated with every HTTP query and this is the primary reason for the long load time. There are some steps you can take to make your WordPress site load faster.

The High Traffic Tips For WordPress guide from WordPress.org claims that “virtually any blogging platform – indeed, any web application – is only able to handle as much traffic as can be supported by the hardware on which it runs.” This is simply not so. Hardware capabilities are important, but efficiency of the web application and its database backend is also a key consideration.

Trimming down CSS and JS

CSS and JS files contain comments, white spaces, control characters – all the stuff that wastes space and is not needed for the file to function correctly. You can trim down these files while retaining full functionality.

Download YUI Compressor from Yahoo. Unzip it to a directory on your server. (In our example the installation directory for YUI Compressor will be /var/adm/bin/yui_compressor/yuicompressor-2.3.5. Let’s assume that your WordPress site is located in /srv/www/htdocs/krazyworks.

Before you start modifying your WordPress installation you must make a backup of your site:

cd /srv/www/htdocs
tar cvf /backups/krazyworks.tar krazyworks
gzip /backups/krazyworks.tar

You should also make a backup of your WordPress database.

Take a look at the script below. The script will scan /srv/www/htdocs/krazyworks andlook for *.css and *.js files. When it finds one, it will make a backup copy of it. Then the script will use YUI Compressor on the original *.css or *.js to trim it down.

#!/bin/sh

# Use Yahoo's YUI Compressor to reduce size of *.js and *.css files
# by removing unnecessary comments and empty spaces. Original files
# are preserved with .before_yui extension.

JAVA="/usr/lib/java/jre/bin/java -jar"
YUICOMPRESSOR="/var/adm/bin/yui_compressor/yuicompressor-2.3.5/build/yuicompressor-2.3.5.jar"
WEBROOT="/srv/www/htdocs"
WEBSITES="krazyworks"
DEFUSER=wwwrun
DEFGRP=www
DEFPERM=755

for SITE in $WEBSITES
do
for FILETYPE in css js
do
find ${WEBROOT}/${SITE}/ -type f -name "*.${FILETYPE}" -print | while read LINE
do
echo "$LINE"
$JAVA $YUICOMPRESSOR --type ${FILETYPE} "${LINE}" > "${LINE}.after_yui"
cp -p "${LINE}" "${LINE}.before.yui"
mv "${LINE}.after_yui" "${LINE}"
chown ${DEFUSER}:${DEFGRP} "${LINE}"
chmod ${DEFPERM} "${LINE}"
done
done
done

Using YUI Compressor will reduce the size of your stylesheets and JavaScript files by 10% or more. This is not much but it helps.

Indexing WordPress database tables

A database index is a data structure that increases speed of operations in a table. The improvement in performance is especially noticeable for random data lookups, such as searching. Table indexes take up more disk space. By indexing your database tables you sacrifice disk space for faster performance.

Once you index a table, every time new data is added to that table, your database software will automatically update the index. For more information about indexing MySQL tables see Creating table indexes in MySQL.

Caching WordPress and database queries

Caching can be done on two levels: inside WordPress and inside the database software. To enable WordPress query caching you can install the WP-Cache plugin for WordPress. This plugin will greatly improve performance of WordPress sites with high user traffic.

Additionally, you can enable caching within MySQL. Open the my.cnf (or my.ini in some versions of MySQL), which is usually located in /etc on Unix systems, and add the following lines to the [mysqld] section near the top of the file:

query-cache-type = 1
query-cache-size = 20M

The first line will enable caching and the second line will set the maximum cache size to 20M. You can increase this number if your web server has lots of RAM. You will need to restart your database (/etc/init.d/mysql restart). It is recommended that you disable all caching – WordPress and MySQL – when your site is in development mode.

Recommended server configuration

The slowest components of your server are electromechanical devices such as hard drives. You want your server to use the hard drives as infrequently as possible and the key to this is having lots of RAM. It is always a good idea to place separate components of your WordPress server on separate hard drives. This way your OS and swap are not interfering with database and the web server.

If your server is limited on RAM, the OS will utilize swap space and so it’s a good idea to place swap on a separate disk. However, if you have plenty of memory and your swap utilization is low, you can keep it on the same drive as the OS. Having database and Apache on separate drive is always a good idea. A multi-threaded, multi-core processor is much more important for a web server than a fast processor.

Below is a sample hard drive configuration for a WordPress server running Linux:

What you have here is machine with two dual SATA RAID controllers (c0 and c1) and two non-RAID controllers (c2 and c3). The primary boot device is the hardware RAID-1 volume. The secondary boot device is the c2d0. You can keep boot0 and boot1 in sync by running a “dd” script once a week. The database files are located on hardware RAID-0 volume for better performance.

The WordPress home directory is on the c3d0. Finally, the c2d1 is a general backup destination for your OS configuration files, database and htdocs backups. Notice how all of your production volumes are on separate controllers for better performance.

With this configuration you can lose any of your primary production volumes and still be able to quickly bring your system up using the backup disks. The performance with the backup volumes will be lower, but this is a temporary inconvenience until you replace the failed drives.

This is not a high-availability configuration – there will be some downtime – but this is still a robust setup done on a budget. To keep your htdocs in sync with the backup disk I suggest you use rsync. You can do the same for cold database backups. Schedule all backups, including boot disk copy, to run during off-peak hours.

CPU considerations

Multi-core processors are preferred in a web application server. You have three groups of processes: the OS, database, and the web server. You can try to assign each group to a separate core of a quad-core CPU. In Solaris you can use “pbind” and in Linux you have “taskset“. This ensures that OS, MySQL, and Apache are not competing with each other for CPU time.

RAM and swap requirements

I would highly recommend that your system has at least 2Gb of RAM if you are running a recent release of Linux, MySQL, and Apache2. Set your MySQL memory utilization so that the database is not eating up all available RAM, otherwise your will be using disk swap space and it will slow things down. However, even if you have plenty of RAM, the size of swap should be double that for systems with 16Gb of RAM or less. For systems with more than 16Gb of memory, the size of swap can be 110% of installed RAM.

If your server has very little memory and experience high swap utilization, it would be a good idea to put swap on its own disk. And if that disk is not on the same controller as the OS disk, that would be even better. This way swapping activity will not interfere with the OS.

Performance monitoring

It’s important to monitor performance of your server and the network. If your users are reporting slow response time for your web site, the first step is to eliminate network as a possible cause. This way you don’t waste your time trying to fix a problem with your server that never existed in the first place.

Installing Webmin is an easy way to get some good performance monitoring tools in one convenient package.

Stress-testing your server

It is important to test your server’s performance under simulated load from time to time. Unfortunately, this is easier said than done. The best way to test if to ask a hundred of your friends with computers to go to your site and start browsing it like crazy. If you are short on friends, however, there are some applications your may try. One thing to keep in mind: stress-testing a server is best done from an external network.

Most of the available web server stress-testing tools are useless garbage. There a couple of notable exceptions, though. The simplest (but not very representative) way of testing a web server is with “wget”. For examle:

time wget -r -l 2 https://www.krazyworks.com/

The parameters used for “wget” are “-r” for “recursive” and “-l” to limit the depth of followed links to two levels. in the end you will get something like this:

Downloaded: 1,537,663 bytes in 83 files
real    0m27.539s
user    0m0.024s
sys     0m0.024s

If you enabled WordPress and database query caching and you run the same “wget” command again, instead of 27 seconds it may take only a couple of seconds to download the same pages.

For more in-depth stress test of your Apache server you can try using the ApacheBench (“ab”) application. Here’s an example of using ApacheBench:

ab -n 100 -k -c 100 -t 30 http://www.slashdot.org/

This will send a hundred requests (-n) at the same time (-c) to the specified URL. The response will look something like this:

Server Software:        Apache/1.3.37 (Unix) mod_perl/1.29
Server Hostname:        www.slashdot.org
Server Port:            80

Document Path:          /
Document Length:        299 bytes

Concurrency Level:      100
Time taken for tests:   1.549 seconds
Sent requests:          100
Completed requests:     100
Failed requests:        0
Total transferred:      51000 bytes
HTML transferred:       29900 bytes
Requests per second:    64.5577792123951
Transfer rate:          32.1528001936733 kb/s received

Connnection Times (ms)
min     avg   max
Connect:      128  678.53  1310
Response:     253  844.66  1440

Warning messages from ab():
[Warn:] None.

HTTP request:
GET / HTTP/1.0
User-Agent: ApacheBench-Perl/0.62
Host: www.slashdot.org
Accept: */*
Connection: Keep-Alive

Once again, keep in mind that running ApacheBench on your web server to test that very same server is like having sex with a pillow. For a more realistic experience find another machine – preferably not on the same local network – and run the test from there.

Another good tool for testing your web server is the Microsoft Web Application Stress Tool. You can use it even if your server is Unix-base. You just need a Windows box to run the test tool. You will need to set IE as you default browser (at least temporarily) if you want to use the “Record Script” feature of this tool.

MS Web Application Stress Tool

Here are a couple of links to some additional information about benchmarking your web server:

  1. Tuning Apache and PHP for Speed on Unix
  2. Performance Tuning

WordPress theme ideas

A few years ago I was running a Web site that was getting about 6,000 hit per day. The server was handling the workload just fine. Suddenly, after some major exposure in the press, the site started getting about 100-200 hits per minute and the server started going under. I started having issues with bandwidth, CPU, RAM, storage – the works. I enabled caching on the database and that took care of much of the CPU load. And I popped an extra few Gig of RAM into the box and that alleviated swap-related issues.

The things that was still killing me was high bandwidth utilization and too many server requests. I needed to cut down on the size and the number of elements in my WordPress pages. So I made a copy of the site’s home directory and lightened up the theme as much as I could by removing unnecessary graphics and recompressing the rest. This took the number of HTTP requests for loading one page from 30-something down to a more manageable 12, and reduced the average wight of a page from almost 300Kb down to less than fifty. And so the site survived the onslaught of the curious.

The moral of the story: it’s a good idea to have a “war-time” version of your web site. Make a copy of it and strip it down to its underwear. It won’t be pretty, but, should you get hit by a tsunami, it will keep your server alive until you relocate to a more capable machine and figure out how you are going to pay for it.

Print Friendly, PDF & Email

8 Comments »

  • We’d love your feedback on our new wordpress monitoring and management tool – see inside your app and see what’s slow, 2 minutes after installing our agent. If you have WordPress performance problems, you should try out New Relic — http://www.newrelic.com – we just released an agent that let’s you see inside your wordpress/php app and see what’s slow. We’d love your feedback. Check out how we do it: http://blog.newrelic.com/2010/12/16/measuring-wordpress-performance-with-new-relic-rpm/

    It is super easy to setup. Let me know if you think this might be valuable!

  • andresumoza says:

    Hi all

    I had this wordpress site with a lot of traffic which is enough to gave my server a hard time. So i would like to implement server-side caching on index.php to improve my website performance

    any suggestion on what kind of approach should i use? i want to write a simple clean code which i can reuse on later time.

    thank you
    “I would like to implement server-side caching on (wordpress) index.php, any suggestion on what kind of approach i should use?” (like using third party cache class or whatever)

    So instead of getting values from database for each request user made, i’d like the request to be cached if possible.

    Anyone else feel this is not detailed enough or do i miss something here?

  • Kaden says:

    Ive always been in a good shape so my condition can be ruled out as a cause.
    Few last years Im having these symptoms in joints, also muscles sore .
    I can barely make tenth part of a distance, that few years ago hardly made me sweat.
    I experience difficulties from very first laps of run.
    Are these bad signs and what should I do?

  • Con Orpe says:

    In jobs I have been in I have always made mistakes. I can’t understand why it just takes me a long time to be able to grasp something and sometimes I don’t always understand. Are some people just slower than others. I’ve always thought I was a bit of a slow learner at school too but I am bright.

  • rashest_hippo says:

    You guys were very helpful with the last video I posted so I was hoping you could help me with this one too? I’m mainly looking for feedback on the dressage portions as this was one of the first times I had ever shown in it and it’s something that I would like to improve. :) Thanks!
    http://www.youtube.com/watch?v=Pzivnu3WsXk

    Also, I have a new training blog:
    maclaychaser.wordpress.com
    Haha thanks, and yeahhh she’s definitely a swisher, she has that “this isn’t interesting enough” personality. Ha.

  • skychi99 says:

    describe how i might denormalize the data to simplify the query.

  • mike s says:

    I’m trying to replicate a WordPress plugin feature in a Drupal environment. Plugin info appears below and here: http://wordpress.org/extend/plugins/wp-youtube-lyte/
    and here: http://blog.futtta.be/wp-youtube-lyte/

    I need embed code or a javascript to do this in Drupal.

    These look and feel like normal embedded YouTube, but only call the actual “fat” Flash or HTML5-player when clicked on, thereby reducing download size & rendering time substantially when embedding YouTube occasionally and improving page performance dramatically when you’ve got multiple YouTube video’s on one and the same page.

  • Thomas A says:

    What his best performance?
    What was his worst performance?
    What’s his most memorable performance?
    What was his greatest boxing achievement?
    mr. van, Hatton wasn’t undefeated. Floyd Mayweather had already beaten him by KO.

Leave a Reply to Con Orpe Cancel reply

%d bloggers like this: