===== 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)