1. Home
  2. Other services
  3. Optimize the performance of my site

Optimize the performance of my site

There are several ways to improve the performance of the site, these methods are relatively generic and should not cause any real concern in the majority of use cases but we recommend that you do not implement them if you do not understand them.

Set expiration dates for static files to force them to be cached by the client browser

A simple method consists in using the expired modules and headers of apache to play on the expirations of the cached files on the browser side, it has the advantage of being usable on all types ofaccommodation (Shared, Premium, VDS or Dedicated) :

In order to avoid that browsers have to reload at each visit (or change of page on the same site for example) some static files (CSS files, images or Javascript scripts for example) sometimes shared on different pages of the site, it is possible to give expiry dates for some files/types of files on the server side (by default the server doesn't give any directive and it's up to the browser to decide whether or not it should ask the server for the files and when to reload them) It is therefore possible to reduce the number of files that the visitor's browser has requested and possibly reloaded on each page or visit and thus allow a faster loading of the site (particularly in the case of a slow connection or a site with a large size).

You can observe the behavior of your browser (and the server) by using the developer tools built into modern browsers. If when moving from one page to another there are requests with the response code 304 Not Modified (Status column), it means that the browser has asked the server for the file again, but the server has not "expired" or changed and has not made the browser re-download the file. If some files are in code 200 but grayed out, it means that the browser did not even ask the server for the file and directly displayed the file that it had in its cache.

To find out if an Etag has been sent, or to find an expiration date for a file or page, click on the [+] to the left of the corresponding GET request and look in the "Responses" section of the "Headers" tab

You will be able to see for example:

Date Wed, 30 Mar 2011 16:30:50 GMT
Apache Server/2.2.17
Last-Modified Tue, 29 Mar 2011 23:58:50 GMT
Etag "179abc5-5921-49fa7d7758280"
Accept-Ranges bytes
Cache-Control max-age=172800
Expires Fri, 01 Apr 2011 16:26:03 GMT
Vary Accept-Encoding
Content-Encoding gzip
Content-Length 5716
Content-Type text/css

Where we can see that an Etag is provided (see below), that the last request to the file is from 30/03/2011 at 16:30, that the last modification of the file (server side) is from 29/03/2011 and that it will expire on 01/04/2011 and that it should not remain more than 172800 seconds in the cache on the client side (beyond that, if it is not already done, the browser will remove it by itself from its cache)

You can use an .htaccess file at the root of the site in question by adding for example :

   FileEtag none
       Header unset Etag
   ExpiresActive on
   ExpiresByType image/jpg "access plus 4 days"
   ExpiresByType image/gif "access plus 7 days"
   ExpiresByType image/jpeg "access plus 4 days"
   ExpiresByType image/png "access plus 4 days"
   ExpiresByType image/x-icon "access plus 7 days"
   ExpiresByType text/css "access plus 48 hours"
   ExpiresByType application/javascript "access plus 48 hours"
   ExpiresByType application/x-javascript "access plus 48 hours"
   ExpiresByType application/x-shockwave-flash "access plus 48 hours"
   ExpiresDefault "access plus 1 days"

The first part (in the FilesMatch directive) means that all files with the extension .ico, .pdf, .flv... will not have an Etag and the Etag will not be transmitted.

The Etag is an identifier created by the Apache server for each file, if the latter is modified the tag will change; this allows the browser to compare the tag sent by the server to the one it has in cache in order to be able to retrieve the file again in case of difference.

The problem is that the Etag header is redundant with the "Last-Modified" header also sent by Apache, this header being accurate to the second it may not be sufficient in the case of dynamic files (files generated on the fly by PHP scripts for example) if they have been modified more than once per second but may be useless in the case of CSS or Javascript files that are modified only rarely (and manually) for example

If Etag is enabled, each time a file is requested, the Apache server will regenerate an Etag by checking the file's last modification date, its size and where it is located on the filesystem; this will consume resources and take more time than just retrieving the last modification date (which is also provided by default), it also implies that the browser has to request the Etag, check if it matches the one it has in cache before eventually requesting the file again, if Etags are disabled the browser will not request the file if it already has it in cache and it is not "expired".

It is also possible to deactivate the " Last-Modified " header by adding in the FilesMatch tag : Header unset Last-Modified

It is recommended to test the behavior of the browser if Etag and Last-Modified are disabled and to set the expiration times with mod_expires accordingly.
Official documentation of the mod_headers

In the second part of the example, the ExpiresByType directive followed by the mimetype is used to define how long files with a specific extension are valid after the last access by the user. This allows a browser, for example, not to recheck its cached jpg files for 4 days by "prioritizing" files that have a longer expiration time over those that do not.
Official documentation of mod_expires

Use of a PHP cache module

There are mainly two types of cache in PHP:

The application cache

The application cache is integrated into the PHP application and will allow not to recalculate at each access to a page all the code, mainly certain parts not changing at each access (for example: the layout which the major part will not change, the inclusion of text contained in a file not having been modified since the last access or calculations which are recurrent with identical parameters).

The "result" of the processing of these parts of code that does not change is saved and then taken up directly at the next use, thus avoiding certain useless calculations/disk accesses, it also avoids having to retrieve certain data from the database server.

Most of the PHP frameworks such as Symfony or Zend offer a cache system in a transparent way for the developer/user, the same goes for most of the CMS and other PHP tools such as PHPBB, Prestashop or WordPress which integrate cache systems (sometimes in the form of modules) which are not activated by default but which once activated allow to increase drastically the performances.

This type of cache is generally deactivated by default because when a theme (or template) is modified, for example, it may not be "re-calculated" immediately and therefore may not display the modifications made directly. It is therefore recommended that when a site's theme is configured, coded or modified, the cache be deactivated (or that its re-creation be forced when possible after modifications have been made).

This type of optimization is probably one of the most interesting in terms of site loading times because the client browser can only begin to download the site files once it has begun to receive the page which, in its HTML code, contains the paths to the other files to be retrieved and, as PHP only sends the page back to the Apache server once it has been completely "generated", if the latter takes longer to generate, the loading of the site will be that much longer.

Server side PHP cache (only for VDS and Dedicated)

The machine code cache also called opcode cache, it caches in memory PHP code pre-computed in machine code and allows to save calculation time and therefore loading time.

This type of cache has the advantage of not requiring any specific adaptation/configuration on the part of the PHP script being executed, any PHP script is compatible and it does not pose a problem with dynamic content. To use this kind of cache, PHP must load an adapted module, the three most common at the moment are eAccelerator, APC and xCache; eAccelerator tends not to be used anymore because it is less maintained than the two last ones and generally less efficient, APC is about as efficient as xCache but has some features less (an administration panel allowing to follow the use of the cache and to check its content is available under xCache for example) but is on the other hand available for a longer period of time (under Debian 4.0 in particular whereas xCache is available as a pre-compiled package only from Debian 5.0). It is therefore possible to install them by typing :

apt-get install php5-xcache

Or :

apt-get install php-apc

(only one of these modules can be used at a time)

You can then adapt the configuration to your needs (cache size, maximum number of entries or enable variable caching for xcache for example)
List of configuration options for xCache
List of configuration options for APC

Compression of data transmitted by the Apache server (VDS, Dedicated, Permium only)

The Apache deflate module allows to compress "on the fly" some files such as html, Javascript or CSS. This module is activated by default on shared hosting and allows to reduce the amount of data to be loaded for the site visitor.

On the default installation of Apache, the deflate module is installed but not necessarily active and its default configuration only compresses html files, it is also possible to use it for CSS and Javascript files (which can be several hundred kilobytes in size depending on the site), the average compression rate is between 50 and 75% on these types of files, which is not negligible

You can see what the files would have weighed with the module enabled by using the Pagespeed module for Firefox (or its version for Google Chrome), by going to the "Pagespeed" tab and then clicking on "Analyze Performance" under "Enable Compression" and getting a message like :

Compressing the following resources with gzip could reduce their transfer size by 100,1KiB (72% reduction). 

This means, in this case, that the page could go from about 150kb to load to 50kb with the compression activated.

To activate the module, simply type the command :

a2enmod deflate

To enable compression of non-html files, you need to modify the /etc/apache2/mods-available/deflate.conf file as is:

# these are known to be safe with MSIE 6
         AddOutputFilterByType DEFLATE text/html text/plain text/xml

         # everything else may cause problems with MSIE 6
         AddOutputFilterByType DEFLATE text/css
         AddOutputFilterByType DEFLATE application/x-javascript application/javascript application/ecmascript
         AddOutputFilterByType DEFLATE application/rss+xml

         BrowserMatch ^Mozilla/4.[0678] no-gzip
         BrowserMatch bMSIEs(7|8|9) !no-gzip !gzip-only-text/html

(the last two lines disable compression for files other than html under ie6 and below which can cause problems by sometimes displaying blank pages)

Then you have to restart Apache by typing this command:

/etc/init.d/apache2 restart

You should now, in "Pagespeed" have a green check next to "Compression Enabled" if you are testing a site hosted on the machine.

Updated on 25 November 2022

Related Articles