===== Introduction =====
Joomla is a fairly populate content management system (CMS). It is a common sense that most Web sites have content that does not change frequently should use caching techniques to reduce load to server and improve end user experience. Joomla itself has three levels of caching:
- Page caching
- View caching
- Module caching
Page caching is the one that significantly improves performance (8 times faster). However, the cache result (in html format) is saved as a php file in docroot/cache/page directory. IOW, php is still invoked to serve these pages.
===== LiteSpeed Caching =====
LiteSpeed webserver (LSWS) cache bypasses php invocation and serves cached page directly from LSCache. Hence a much bigger performance improvement can be achieved.
==== Joomla Code Change ====
To work with Joomla (cached for either guest visitor or logged-in user), LSCache relies on a cookie token to differentiate whether a user is logged in or not. However, Joomla assigns cookie to any user (guest and logged-in). cookie value changes as same session go through different stage (such as before login, after login, logout and log back in, etc) while cookie key stays the same. The easy way is the create desired cookie in joomla by modifying its code (small modification in login/logout stage). Login/Logout functions are located in the standard user component (docroot/component/com_user/controller.php).
The modification is as follows:
function login() {
if(!JError::isError($error))
{
// Redirect if the return url is not registration or login
if ( ! $return ) {
$return = 'index.php?option=com_user';
}
setcookie("loginuser","yes"); // <==== add this line # add "loginuser=yes" cookie upon successful login
$mainframe->redirect( $return );
function logout ()
if(!JError::isError($error))
{
setcookie("loginuser", "", time()-86400*365); // <=== add this line # drop "loginuser" cookie upon logout.
if ($return = JRequest::getVar('return', '', 'method', 'base64')) {
$return = base64_decode($return);
if (!JURI::isInternal($return)) {
$return = '';
}
}
Once test ok, implement rewrite rules to enable LSCache for the resources that required caching.
==== Rewrite rules for LSWS caching ====
In file joomla_docroot/.htaccess
########## Begin - Joomla! core SEF Section
#
RewriteRule p.php - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
#
########## End - Joomla! core SEF Section
Change to
########## Begin - Joomla! core SEF Section
#
RewriteRule p.php - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/index.php
RewriteCond %{REQUEST_URI} (/|\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule (.*) index.php
#### There is no need for this ENV
#RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
#
########## End - Joomla! core SEF Section
########## Begin - Rules for LSCache
RewriteCond %{REQUEST_METHOD} ^HEAD|GET$
RewriteCond %{HTTP_COOKIE} !loginuser
RewriteCond %{ORG_REQ_URI} !^/index.php$
RewriteCond %{ORG_REQ_URI} !^/administrator/
RewriteCond %{ORG_REQ_URI} (\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$ [NC]
RewriteRule .* - [E=Cache-Control:max-age=300,L]
########## End - Rules for LSCache
Explanation of the added rules:
- Only cache for Head or Get requests
- Cache for guest user (no loginuser cookie)
- Cache request to any URLs like ((\.php|\.html|\.htm|\.feed|\.pdf|\.raw|/[^.]*)$) but excluding /index.php, and /administrator/*
- Cache for 300 seconds
**Note:**
- Joomla's login form (index.php) is not cache friendly (contain a security token) and has to be excluded from being cached.
- /administrator/* is the Joomla backend. No need to be cached.
LSCache Policy configuration (Admin Console -> Server/Vhost ->Cache-> Cache Policy).
==== LSCache Policies ====
Cache Policy:
Enable Cache: ==> No
Cache Expire Time (seconds): => Not Set
Cache Request with Query String: => Yes
Cache Request with Cookie: => Yes
Cache Response with Cookie: => Yes
Ignore Request Cache-Control: => Yes
Ignore Response Cache-Control: => Yes
Enable Private Cache: => Yes
Private Cache Expire Time (seconds): => 120
To verify if a resource is served out of LSCache is simple, just look for "X-LiteSpeed-Cache: hit,private" in server response header. If the header is present, the resource IS served from LSCache.
HTTP/1.1 200 OK
Content-Encoding: gzip
Vary: Accept-Encoding
Date: Tue, 08 Feb 2011 23:14:38 GMT
Server: LiteSpeed
Connection: Keep-Alive
Keep-Alive: timeout=5, max=100
**[COLOR="red"]X-LiteSpeed-Cache: hit,private[/COLOR]**
Content-Length: 6141
X-Powered-By: PHP/5.2.11
P3P: CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
Content-Type: text/html; charset=utf-8
Expires: Mon, 1 Jan 2001 00:00:00 GMT
Last-Modified: Tue, 08 Feb 2011 23:14:12 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
===== Benchmark Comparison =====
Following is the ab benchmark of the test sites in our lab against latest Joomla 1.5 (1.5.22) with sample data comes with install.
Litespeed Cache + Joomla 1.5.22 (with NO system cache plugin)
Benchmarking 192.168.0.56 (be patient).....done
Server Software: LiteSpeed/4.1RC4
Server Hostname: 192.168.0.56
Server Port: 8088
Document Path: /joomla-overview.html
Document Length: 12422 bytes
Concurrency Level: 10
Time taken for tests: 0.139489 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 1363478 bytes
HTML transferred: 1316732 bytes
Requests per second: 716.90 [#/sec] (mean)
Time per request: 13.949 [ms] (mean)
Time per request: 1.395 [ms] (mean, across all concurrent requests)
Transfer rate: 9541.97 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 5 12 4.2 12 22
Waiting: 5 11 3.9 11 21
Total: 5 12 4.2 12 22
Percentage of the requests served within a certain time (ms)
50% 12
66% 12
75% 13
80% 15
90% 21
95% 21
98% 22
99% 22
100% 22 (longest request)
Joomla 1.5.22 with Page Caching (system cache plugin)
Benchmarking 192.168.0.56 (be patient).....done
Server Software: LiteSpeed/4.1RC4
Server Hostname: 192.168.0.56
Server Port: 8088
Document Path: /joomla-overview.html
Document Length: 12537 bytes
Concurrency Level: 10
Time taken for tests: 2.492758 seconds
Complete requests: 100
Failed requests: 0
Write errors: 0
Total transferred: 1306000 bytes
HTML transferred: 1253700 bytes
Requests per second: 40.12 [#/sec] (mean)
Time per request: 249.276 [ms] (mean)
Time per request: 24.928 [ms] (mean, across all concurrent requests)
Transfer rate: 511.48 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.0 0 0
Processing: 51 243 159.6 215 1226
Waiting: 43 203 147.5 181 1080
Total: 51 243 159.6 215 1226
Percentage of the requests served within a certain time (ms)
50% 215
66% 256
75% 275
80% 283
90% 324
95% 436
98% 959
99% 1226
100% 1226 (longest request)
Joomla 1.5.22 with NO Page Caching
Benchmarking 192.168.0.56 (be patient).....done
Server Software: LiteSpeed/4.1RC4
Server Hostname: 192.168.0.56
Server Port: 8088
Document Path: /joomla-overview.html
Document Length: 12490 bytes
Concurrency Level: 10
Time taken for tests: 9.218677 seconds
Complete requests: 100
Failed requests: 92
(Connect: 0, Length: 92, Exceptions: 0)
Write errors: 0
Total transferred: 1296527 bytes
HTML transferred: 1246727 bytes
Requests per second: 10.85 [#/sec] (mean)
Time per request: 921.868 [ms] (mean)
Time per request: 92.187 [ms] (mean, across all concurrent requests)
Transfer rate: 137.33 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.9 0 5
Processing: 256 893 578.1 748 3065
Waiting: 248 828 567.9 694 2878
Total: 256 893 578.1 748 3065
Percentage of the requests served within a certain time (ms)
50% 748
66% 868
75% 933
80% 1058
90% 1672
95% 2396
98% 2892
99% 3065
100% 3065 (longest request)