PHP xcache performance tuning tutorial on Lighttpd

A tutorial on php + xcache for serving webpages directly from server RAM

A typical PHP application and most of the frameworks uses “The Loop” method to code the website. Whenever request comes to website, It’s typically sent to index page to handle every parameters.

// The world's simplest index page, also called The Loop
get_header();
if (have_action()) :
	if(found_action()):
		include(action);
	else:
		header("404");
else :
	  include("homepage");
endif;
get_footer();

Above code describes typical PHP application routing for template based websites. This style of coding can be converted into enterprise PHP framework with use of design patterns (i.e interfaces like pear, Template engine like smarty, use of MVC).

Xcache and Lighttpd

Xcache optimize PHP performance by keeping most frequently used code into server RAM. i.e. Once code is cached, repeated requests are directly served without recompiling. There are several PHP accelerators are available that goes well on different environments i.e. APC, memcache, xcache, static cache etc.

Accelerator on Lighttpd No of Requests Concurrent connections Serving Time
static File Cache 20000 5 43 seconds
memcache 20000 5 19 seconds
xcache 20000 5 13 seconds

I made some ab (apache benchmark) test on lighttpd with xcache, memcache and static file cache & I have to conclude that Lighttpd and Xcache combination gives best php performance.

Best Pairs of Accelerator + Web Server

  • APC + Apache = Best performance
  • Memcached + Nginx = Best performance
  • Xcache + Lighttpd = Best performance

The Loop Framework with Xcache

We can use xcache variables to store entire web page and serve it from RAM.

Xcache Functions

  • xcache_isset($key) – Checks for $key exist in xcache
  • xcache_set(“key”,”value”,$timeout) – Sets variable in xcache for $timeout seconds
  • xcache_get(“key”) – Gets variable from xcache
  • xcache_unset(“key”) – Removes variable from xcache

Using xcache with php to optimize website.

// Init Caching
include("xcache.php"); // Including Xcache Library... (find code below)
define('HTML_CACHE',true); // set this to false when you need to turn off xcache feature
$cacheConfig['cachepage'] = true; // for mobile useragent you may turn it off for fetching and displaying ads.
init_caching();

get_header();
if (have_action()) :
	if(found_action()):
		include(action);
	else:
		header("404");
else :
	  include("homepage");
endif;
get_footer();  

// Finish Caching
finish_caching();

xcache.php

// code for xcache.php
global $cacheConfig;
$cacheConfig = Array();
$cacheConfig['timeout'] = 10800; // 3 hours
$cacheConfig['page'] = md5("http://".$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']);
$cacheConfig['savepage'] = false;
$cacheConfig['cachepage'] = false;

function cacheEnabled() {
	if (!defined('HTML_CACHE') || (defined('HTML_CACHE') && HTML_CACHE != true)) {
		return false;
	}else{
		return true;
	}
}

function init_caching() {
	if (!cacheEnabled()) {
		return;
	}
	global $cacheConfig;
	if ($cacheConfig['cachepage'] == true) {
	startHTMLCache();
	}
}

function finish_caching() {
	if (!cacheEnabled() ){
		return;
	}
	global $cacheConfig;
	if ($cacheConfig['savepage'] == true) {
	endHTMLCache();
	}
}

function endHTMLCache() {
		global $cacheConfig;
		$content = ob_get_contents();
		ob_end_clean();
		xcache_set($cacheConfig['page'],$content,$cacheConfig['timeout']);
		echo $content;
		exit;
}

function startHTMLCache() {
		global $cacheConfig;
		if (xcache_isset($cacheConfig['page']))	{
			echo xcache_get($cacheConfig['page']);
			exit;
		}
  		else {
    	  $cacheConfig['savepage'] = true;
		   ob_start();
  	 	}
}

Upgrading php 5.1 to php 5.3 with xcache rebuild on centos 5

Upgrading PHP 5.3 on CentOS 5

CentOS 5 comes with php 5.1 version. There is no official PHP 5.2+ release forĀ  upgrade since last 3 years. So, It was hard for any php developer to work with new php functions like json_encode, json_decode and powerful frameworks like symfony and cakephp 2

As a result, Developer had to implement alternative functions to integrate twitter, myspace OAuth API. Today wordpress has officially said bye bye to php 4 and mysql 4. So finally, I gathered some courage to mess with my current php installation.

I followed the following steps to upgrade php 5.3 on centos 5.

Adding webtatic repository to yum for php 5.3 upgrade

su
cd ~
rpm -ivh http://repo.webtatic.com/yum/centos/5/`uname  -i`/webtatic-release-5-0.noarch.rpm

Updating PHP with yum

yum --enablerepo=webtatic update php

Up to this point, everything had executed perfectly, including dependency resolving.

After upgrading PHP 5.3, when I tried to browse my site homepage, I got blank page!

I thought now I went into deep trouble, I shouldn’t had taken the risk but then I thought lets check all sites hosted on my server. Fortunately they were working correctly. So as computer engineer, I started digging into problem with basics. Just added 2 lines of error debugging code into my header file.

error_reporting(E_ALL);
ini_set("display_errors",1);

Got xcache error: function xcache_isset() not defined on line blah… So I got it. I checked for php version.

php -v

Everything was there but xcache was missing. Finally I got the clue, I have to rebuild xcache with newer version of php. So I rebuild the xcache.

XCache 1.3.0 rebuild commands for PHP 5.3 on CentOS 5

wget http://xcache.lighttpd.net/pub/Releases/1.3.0/xcache-1.3.0.tar.gz
tar -xzvf xcache-1.3.0.tar.gz
cd xcache-1.3.0/
phpize --clean
phpize
./configure --enable-xcache && make
make install

That’s it. After restarting lighttpd, my homepage started working correctly.