Serving Cached Data For Improved Performance

Jul 14, 02:24 am

Over the past day I've been going through a few web applications and preparing them in the event they get digged or slashdotted. One of my primary goals was to cache as much data to disk, rather than hitting the database for it each time. Now, most of the web applications I have written myself, so I didn't have the luxury of some type of pre-made mod or plug-in. In one case, this textpattern installation, I did have that luxury.

For the textpattern installation, I just used the wonderful asy-jpcache plug-in. It does full page caching, which is what I was looking for in this instance. It will expire the cache when an article is added, edited, or deleted. It also expires the page cache if a comment is posted. Enabling page level caching in this textpattern installation has made us able to serve roughly 20 times the number of pages before reaching a critical load. Quite impressive!

If you are interested in doing content level caching in textpattern, I recommend you look at the zem-cache plug-in.

For my self written web applications, I still didn't want to reinvent the wheel (who does?), so I used a caching library that I've used for a couple of years. It was written by a really smart guy named Jon Bardin (who I haven't spoken to in a couple of years). You can find source for the library here.

Using it is very simple. Let's say you have some code that looks like such:

php:
<?php
$result = mysql_query("select * from foo");
while($row = mysql_fetch_assoc) {
  echo "$row[0] : $row[1] <br />\n";
}
?>

Utilizing the caching library, that code would become something like:

php:
<?php
include('cachelib.php');
$varcache = New Cache("footable", 600);
if($varcache->cacheObjectTimedOut()) {
  $result = mysql_query("select * from foo");
  $display = '';
  while($row = mysql_fetch_assoc) {
    $display.= "$row[0] : $row[1] <br />\n";
  }
  $varcache->updateCacheObject (serialize ($display));
} else {
  $display = unserialize ($varcache->loadCacheObject());
}
echo $display;
?>

One thing to note is how, while looping through the rows, I stored the data in a variable rather than immediately sending it to the browser. This is necessary so that we can serialize and stuff the data into the cache and be able to pull it out later.

As you can see, this is much modification to existing code and the benefits gained from such caching are tremendous.

Another method that is helpful is being able to expire the cache anytime you want. For instance if you were caching your main index page that listed the last 5 news items, you would want to expire the cache anytime you updated, added, or deleted news. The way to do that is as such:

php:
<?php
require_once('cachelib.php');
$varcache = New Cache("footable", 600);
while(!$varcache->deleteCacheObject());
?>

Obviously caching of data alone is not going to save your server from a sudden large spike in traffic such as what digg or slashdot will send, but it certainly will help. Along with caching you should be looking at your web server configs, database configs, and operating system configs. All will need to be tweaked and tested.



    1. You can also do this with memcached and PHP’s memcache functions. Using memcached requires that you run the server outside of PHP but that also allows you to use it from multiple servers.



    1. Yes, memcached is an excellent solution as well. Unfortunately, many people don’t have access to load PECL modules and it is not included in the PHP distribution. Thanks for pointing it out!




Add your comments

Please keep your comments relevant to this blog entry: inappropriate or purely promotional comments may be removed. To add hyperlink, please follow this example: "your link text":http://your.link.url