Speed ​​up Joomla 1000 times

    Target audience: programmers, Joomla administrators and other users with elementary skills in working with PHP.

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

    And what next, change the CMS? Of course change, but too often, users ask back to Joomla. Immediately make a reservation, the task of the article is not to affect the choice of CMS, to discuss the speed of various CMS solutions or the disadvantages of Joomla architecture.

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

    Joomla works under PHP, even if caching is used 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 unattainable. We force Joomla to save a copy of the generated page to disk, and Apache to 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. At Joomla, we use the Article type, which just represents a page with static content.

    Create a new plugin for Joomla, just two files:

    htmlcache.xml - plugin description file


    System - HTML cache

    March 2010

    www.gnu.org/licenses/gpl-2.0.html GNU/GPL


    0.6
    Creates static HTML versions of content pages. It will only cache SEO URLs, *.php pages will not be cached.

    htmlcache.php










    * 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 Article type, create a folder structure in the html_cache_dir directory in accordance with the website structure 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, thereby increasing the website’s performance.

    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 form will be cached:
    / about
    / software / catalog


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

    htmlcache.php - the code itself.
    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;
          $ 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->
          if (strpos ($ relativePath, '.')) {return; } // exit if found DOT in the request_uri, we do not want to cache anything other than SEO
          $ 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 admin interface. After installation, set 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 works and everything is fine with write permissions.

    It remains to force Apache to give these files without calling the PHP code. In .htaccess, immediately after RewriteEngine on add: Restart apache and check through the browser. In order to check the performance, run (under Linux):
    RewriteCond %{REQUEST_URI} (/|/[^.]*)$ [NC]
    RewriteCond %{DOCUMENT_ROOT}/cache/content/%{REQUEST_URI}/index.html -f
    RewriteRule (.*) /cache/html/$1/index.html [L]


    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 a warm-up for Apache. You can run it on the web server itself to eliminate delays in the network or over the network, but the numbers will be different.

    Replace www.azati.com with your server address; www.azati.com can be tested for comparison. We’re not afraid, the site does not fall and google statistics do not spoil.

    Unfortunately, speed is not in vain:
    - The ability to edit Articles through the Joomla front-end, only through the administrative interface, disappears.
    - After editing the article, you need to clear the cache through the administrative interface Tools -> Clean cache

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

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

    Also popular now: