📜 ⬆️ ⬇️

Accelerate Joomla 1000 times

Target audience: programmers, Joomla administrators and other users with basic PHP skills.

Joomla - slow, very slow. Joomla out of the box can rarely issue more than 4 requests per second. Turn on the cache, set the PHP accelerator, work on optimization, and maybe we can get 20 requests per second.

And what's next, change the CMS? Of course, change, but too often, users are asked back to Joomla. Immediately make a reservation, the task of the article does not affect the choice of CMS, discuss the speed of various CMS solutions or the shortcomings of the Joomla architecture.

These recommendations will be helpful if:
- you or your client have a website on Joomla
- your site consists mainly of static content
- it is not enough for you to receive from the server 20 requests per second, you need 2000-3000.
- you think about how much website response time affects the google rating. Some info on this topic here googlewebmastercentral.blogspot.com/2010/04/using-site-speed-in-web-search-ranking.html

Joomla works under PHP, even if you use caching at the level of Joomla modules, PHP is still used and the page is rendered every time it is accessed. This means that speeds of 2000 requests per second will be unreachable. Make Joomla save a copy of the generated page to disk, and Apache read this copy directly, bypassing PHP for all subsequent users. This is a good old approach, which by the way can be applied to other CMS, but only for static content. On Joomla, we use the Article type, which represents the page with static content.
')
Create a new plugin for Joomla, just two files:

htmlcache.xml - plugin description file
<? xml version ="1.0" encoding ="utf-8" ? >
< install version ="1.5" type ="plugin" group ="system" >
< name > System - HTML cache </ name >
< author ></ author >
< creationDate > March 2010 </ creationDate >
< copyright ></ copyright >
< license > www.gnu.org/licenses/gpl-2.0.html GNU/GPL </ license >
< authorEmail ></ authorEmail >
< authorUrl ></ authorUrl >
< version > 0.6 </ version >
< description > Creates static HTML versions of content pages. It will only cache SEO URLs, *.php pages will not be cached. </ description >
< files >
< filename plugin ="htmlcache" > htmlcache.php </ filename >
</ files >
< params >
< param name ="html_cache_dir" type ="text" default ="" label ="HTML Cache dir" description ="Set the joomla HTML cache directory." />
< param name ="cache_view_1" type ="text" default ="article" label ="View to cache 1" description ="Set view type to be cached. Only HTTP content can be cached." />
< param name ="cache_view_2" type ="text" default ="" label ="View to cache 2" description ="Set view type to be cached. Only HTTP content can be cached." />
< param name ="cache_view_3" type ="text" default ="" label ="View to cache 3" description ="Set view type to be cached. Only HTTP content can be cached." />
< param name ="cache_view_4" type ="text" default ="" label ="View to cache 4" description ="Set view type to be cached. Only HTTP content can be cached." />
</ params >
</ install >

* This source code was highlighted with Source Code Highlighter .


Now create an onAfterRender event handler. The task of the handler is to intercept only articles of the type Article, create in the html_cache_dir directory a structure from folders in accordance with the structure of the website and save the page content there. Additionally, before saving, you can run the page through the HTML optimizer (for example, this Minify_HTML ), which optimizes the page size, removing unnecessary comments and spaces and thereby increasing the efficiency of the website.

Separately, we note that this code works for websites with SEO enabled and does not cache pages with any extensions like php or html. Only URLs of the following type will be cached:
/ about
/ software / catalog


The code will have to be corrected if you are not using SEO.

htmlcache.php - directly code.
<? php
defined ( '_JEXEC' ) or die ( 'Restricted access' ) ;
jimport ( 'joomla.plugin.plugin' ) ;
class plgSystemHtmlcache extends JPlugin
{
function plgSystemHtmlcache ( & $ subject , $ config )
{
parent :: __construct ( $ subject , $ config ) ;
}

function onAfterRender ( )
{
global $ mainframe ;
if ( $ mainframe -> isAdmin ( ) ) { return ; } // do not cache admin pages

$ document = & JFactory :: getDocument ( ) ;
$ doctype = $ document -> getType ( ) ;
$ user = & JFactory :: getUser ( ) ;
if ( $ user -> get ( 'guest' ) ! = 1 ) { return ; } // Only cache for non logged in users
if ( $ doctype ! = 'html' ) { return ; } // Only render for HTML output
$ html_cache_dir = $ this -> param ( 'html_cache_dir' ) ;
if ( $ html_cache_dir == '' ) { return ; } // Exit if no html_cache_dir specified
if ( ! file_exists ( $ html_cache_dir ) ) { mkdir ( $ html_cache_dir ) ; } // try to create folder if it does not exist
// Only render for provided views
if ( ( JRequest :: getVar ( 'view' ) ) ! = $ this -> param ( 'cache_view_1' ) &&
( JRequest :: getVar ( 'view' ) ) ! = $ This -> param ( 'cache_view_2' ) &&
( JRequest :: getVar ( 'view' ) ) ! = $ This -> param ( 'cache_view_3' ) &&
( JRequest :: getVar ( 'view' ) ) ! = $ This -> param ( 'cache_view_4' ) ) { return ; }
$ relativePath = $ this -> request_uri ( ) ;
if ( strpos ( $ relativePath , '.' ) ) { return ; } // exit if found in the request_uri
$ relativePath = str_replace ( '/' , DS , $ relativePath ) ;
// $ body = Minify_HTML :: minify (JResponse :: getBody ());
$ body = JResponse :: getBody ( ) ;
$ fullPath = $ html_cache_dir . $ relativePath ;
$ parts = explode ( DS , $ relativePath ) ;
$ currentPath = $ html_cache_dir . DS ;

foreach ( $ parts as $ p ) {
if ( $ p == '' ) {
continue ;
}
$ currentPath . = $ p ;
if ( ( ! file_exists ( $ currentPath ) ) && ( ! is_file ( $ currentPath ) ) ) {
mkdir ( $ currentPath ) ;
}
$ currentPath . = DS ;
} // end for each
$ indexFile = $ currentPath . DS . 'index.html' ;
if ( ! file_exists ( $ indexFile ) ) { $ this -> writeToFile ( $ indexFile , $ body ) ; }
}

function writeToFile ( $ fileName , $ content ) {
$ handle = fopen ( $ fileName , 'w' ) ;
fwrite ( $ handle , $ content ) ;
fclose ( $ handle ) ;
}

function request_uri ( ) {
if ( isset ( $ _SERVER [ 'REQUEST_URI' ] ) ) {
$ uri = $ _SERVER [ 'REQUEST_URI' ] ;
} else {
if ( isset ( $ _SERVER [ 'argv' ] ) ) {
$ uri = $ _SERVER [ 'PHP_SELF' ] . '?' . $ _SERVER [ 'argv' ] [ 0 ] ;
} else {
$ uri = $ _SERVER [ 'PHP_SELF' ] . '?' . $ _SERVER [ 'QUERY_STRING' ] ;
}
}
return $ uri ;
}

function param ( $ name ) {
static $ plugin , $ pluginParams ;
if ( ! isset ( $ plugin ) ) {
$ plugin = & JPluginHelper :: getPlugin ( 'system' , 'htmlcache' ) ;
$ pluginParams = new JParameter ( $ plugin -> params ) ;
}
return $ pluginParams -> get ( $ name ) ;
}
}


Both files can be downloaded to / plugins / system or placed in htmlcache.zip and installed via the Joomla administrative interface. After installation, set the html_cache_dir = / opt / www / html / cache / content in the plugin settings and enable the plugin (Enabled: Yes).
When you first access the page in the folder / opt / www / html / cache / content folders and files should appear - this means that the plugin is working and everything is in order with write permissions.

It remains to force Apache to give out these files without accessing the PHP code. In .htaccess, immediately after RewriteEngine on add:
RewriteCond %{REQUEST_URI} (/|/[^.]*)$ [NC]
RewriteCond %{DOCUMENT_ROOT}/cache/content/%{REQUEST_URI}/index.html -f
RewriteRule (.*) /cache/html/$1/index.html [L]

Restart apache and check through the browser. In order to check the performance of the run (for Linux):
ab -n 10000 -c 50 -k www.azati.com
...
Concurrency Level: 50
Time taken for tests: 4.294054 seconds
Complete requests: 10000
Failed requests: 0
Write errors: 0
Keep-Alive requests: 10000
Total transferred: 71155755 bytes
HTML transferred: 67695750 bytes
Requests per second: 2328.80 [#/sec] (mean)
Time per request: 21.470 [ms] (mean)
Time per request: 0.429 [ms] (mean, across all concurrent requests)
Transfer rate: 16182.38 [Kbytes/sec] received
...

It is better to run the test several times to provide “warming up” for Apache. You can run on the web server itself to eliminate network or network latency, but the numbers will be different.

www.azati.com Replace with your server address, www.azati.com can be tested for comparison. We are not afraid, the site does not fall and google statistics does not deteriorate.

Unfortunately, speed is not a gift:
- Lost the ability to edit articles (Articles) through Joomla front-end, only through the administrative interface.
- After editing the article, you need to clear the cache through the administrative interface Tools -> Clean cache

Weigh and decide whether the approach is justified for your website.

PS If you have dynamic content, you can organize periodic cleaning of the cache (for example, once an hour), and thereby get a fast site that is updated quite often.

Source: https://habr.com/ru/post/92783/


All Articles