Optimizing WordPress performance on EC2 micro

I wanted to host a fast loading blog on an EC2 micro. The following data was built by going through the different optimization options easily available to all WP users.
Among some optimizations to minimize load-time that didn’t make the cut were tweaks to how jQuery and Google Analytics were loaded.

Running any benchmarks on an EC2 micro is damn hard, and that deserves its own post. But even after accounting for “cpu-stealing”, the numbers still suffer from a jitter of ~100msec.

“disk-cache” = Amazon’s EBS (persistent storage).
“apc-cache” = In memory PHP extension.

Stack:

  • Amazon’s Linux AMI 2012 (CentOS based) with EBS backing
  • MySQL 5.5
  • Apache 2.2
  • PHP 5.3 (mod_php) + APC 3.1 op-code and user-objects cache (op-code caching on for all tests)
  • WordPress 3.4 with W3 Total Cache

The numbers below will make more sense if you keep in mind that disk-caching will rarely hit the disk; files will stay warm in the filesystem’s cache.

Individual Optimizations

Optimization HTML fetched DomContentLoaded event Load event
No Caching 550ms 0.9s 1.0s
DB Caching (disk) 620ms 1.0s 1.1s
DB Caching (apc) 540ms 1.0s 1.1s
Object Caching (disk) 500ms 1.0s 1.2s
Object Caching (apc) 470ms 1.1s 1.2s
Minify JS/CSS (disk) 550ms 1.1s 1.4s
Minify JS/CSS (apc) 550ms 1.2s 1.4s
Page Caching (disk) 80ms 0.5s 0.6s
Page Caching (apc) 80ms 0.5s 0.7s

 

Combined Optimizations

Optimization HTML fetched DomContentLoaded event Load event
Page Caching + Minify JS/CSS (disk) 80ms 500ms 700ms
Page Caching + Minify JS/CSS (disk) + gzip 60ms 300ms 600ms
Page Caching + Minify JS/CSS (disk) + gzip + jquery.cdn 60ms 200ms 400ms

Lessons learned:

  • Page Caching was the single biggest optimization.
  • Object/DB caching didn’t do much.
    • Probably because WordPress’s massive PHP codebase is a monster compared to some simple MySQL queries (in a small database).
  • Minifying JS/CSS is interesting. A single large 300KB JS blob is worse than multiple 50KB files downloaded in parallel.
  • jQuery is slow as fuck. But we should all already know that. No matter how you include it (minimized, cdn) you pay a price (~100ms extra until Load event) even if you don’t use it.
    • Throwing jQuery into a gzipped minified format and grabbing from a popular CDN is a great middle ground.

APC was a bad choice for object caching and db caching. Even with my minimal theme, WordPress generated thousands of “objects” to store in APC. This quickly led to memory fragmentation. The overhead for storing & retrieving the objects must have been greater than simply rebuilding them; in every case I found “disk-based” caching to outperform APC on the EC2 Micro.

There was very little I/O happening during these tests due to the file-system caching all of the commonly accessed files. So saying that “disk-cache” is faster than APC is only true because the “disk-caching” option has built in RAM-based caching thanks to the OS.

With page caching, minifying js/css to disk, gzipping it all, and pulling jQuery.min from a fast CDN, an uncached website hit reaches Loaded event in under 400ms.

Bonus: Using a MaxCDN pull-zone to serve all non-html content means that the server only has to do minor PHP work and serve cached html :)

With multiple CDN offloading an uncached hit reaches the Loaded event in under 300ms!

 

Leave a Reply

Your email address will not be published. Required fields are marked *