Hints to help optimise the performance of a PHP website (LAMP)

Over time, the websites I have been involved in have became more and more complex (and indeed carry more and more traffic).

And so the ever increasing need to optimise and increase the performance of your website (or web-application) becomes more crucial.

As you will appreciate this is a HUGE subject, so I aim to simply put you on the path to devising a better architecture and design. But I will attempt to introduce some ideas to assist…

I will mainly concentrates on PHP but the principles here can be translated to any platform really (I have also worked extensively with ColdFusion and Java with making use of similar tools for each).

One thing to also note, much of the information suggested in the ‘advanced’ section of this will be more relevant if you can customise your web-servers directly such as dedicated hosting/data-centers. The basic stuff is largely do-able by anyone who has the skill and patience.

Basics:

OK So, before the need to look at some lower-level solutions and tools (which I will discuss below), there are many simple steps that can be taken to improve your site’s

performance just by putting a little effort in. Much of this also has little to do with PHP directly – so can be applied to general web development.

Validating HTML and CSS – often overlooked, but if the HTML that is being generated is bloated or invalid then the rendering engine of your browser will be slowed down trying to fix your HTML on-the-fly.

Combine multiple CSS files, and JavaScript Files if possible – Also, loading JavaScript files before the

If possible use a CDN (Content Delivery Network) for loading libraries such as jQuery, doing so will load these im parallel and so will not affect page load. If you don’t want to use someone else’s CDN, Alternatively, you could set up a second host-name to host static content (such as css/scripts/images). This again will then be

served in parallel to improve load-time.

Just remember tho if your are using jQuery, unless the document has finished loading and the DOM is ready, things may not work so, either keep jQuery at top, or if possible wrap any jQuery code in, $(document).ready. The $(document).ready function says not to run until the DOM has finished being instantiated – so moving it to after body is okay so long as the JQuery library is loaded first. This may be unconventional and some assumptions may not be correct anymore but does generally work.

The main argument to move scripts to the bottom, is to allow other assets to get downloaded first, i.e. CSS & images etc which will speed up apparent rendering times.

This is because HTTP 1.1 recommends only downloading 2 items per host-name. And you would definitely want your CSS file to be one of the first files downloaded, rather than JavaScript which could make the site appear to render slower (just by the fact that the browser hasn’t got the CSS file yet and isn’t sure what it should do with the HTML).

There are also some simple tricks such as enabling HTTP Compression on your web-server.

The process of minifying (is the process of removing all unnecessary characters from source code, without changing its functionality) CSS/JS has shown to be a good aide too, there are several tools out there that will take some JavaScript and spit back a minified version.

Finally… Some PHP-specific stuff coming up… A valuable tool I have found while developing is code profiling, such as using XDebug + kcachegrind (webgrind) to view the profile data. This is excellent at showing you any bottlenecks in your code so you can pin-point a starting point when trying to make things run smoothly.

Also, simply effectively managing includes files can also help a lot in the the performance, like eliminating unwanted includes files on page. Why include 1000’s of lines of code when it’s not needed? Which could also raise the question – do you really need that bloated framework if you are using one?

A big bottleneck will be in your SQL queries. Sadly the Database expertise of many developers is limited to simple SELECT statements – OK that might be a bit harsh – but ensure your underlying database has been DESIGNED and not flung together, especially if functionality requires extensive queries and joining of lots of data. Another thing overlooked by many people (even advanced developers) is the proper use of Joins, Replication and – very important – proper Indexes on tables.

Also, Stored Procedures are a huge benefit… Ideally once a query is well proven it’s sometimes good practice to move them into Stored Procedures this way the Database Server will do all the hard work and not the PHP thread.

Some Advanced ideas…

So, you’ve done all the above stuff … But still lacking performance? Time to approach it from a different angle. Lets look at some more advanced approaches…

Using a combination of PHP and a reverse proxy such as Varnish/nginx and possibly ditching trusty old Apache for something like Lighty (lighttpd – www.lighttpd.net/) will go miles towards some simple speed and reliability improvements.

Reverse proxies such as Varnish/nginx offer an array of tools to handle dynamic content:

– you can keep cache on certain urls or url patterns to e.g. 5 min
– you can invalidate cache on a url or group of url’s when certain piece of content get’s updated
– you can only cache when certain session is not enabled (e.g. login)

In addition they can modify headers on any files that it serves, e.g. images, pdf’s and so on. I especially like option to serve stale cache during busy periods.

Lighty? Lightly (lighttpd) is an extremely efficient web-server designed and optimised for high performance environments. This means load balancing… basically Lighty will allow you to configure a single server to farm out requests (load balance) to several different machines thus increasing the power of your site. You could even configure it to process specific type of requests to specific server(s) i.e. set up some servers for churning and generating pages and others to handle say Ajax requests for example.

Making use of caching is the final piece. Basically Memcached (and others such products) provide an in-memory store for small chunks of arbitrary data (strings, objects) from results of database calls, API calls, even page rendering. So for data that is constantly being access but being updated in frequently using this is a great approach. Also with Memcached this can also be distributed across servers. Generally all you need – obviously – is to ensure you have enough RAM to dedicate!

You can cache database content and other objects, obviously data that changes very frequently you may not want to cache, but for data where you can live with a slight delay in fully ‘live’ data you can make use of something like MEMCache/APC PHP Cache it being updated frequently.

Lastly another element to add to all that could be a customised implementation of PHP such as PHP FPM ( http://php-fpm.org/ ) – which is a fork of the main PHP project which provides better threading and process spawning… also good for sites of any size. Another good ‘hack’ of PHP is http://www.xarg.org/2011/06/php-hacking/ which introduces some simple enhancements that should really be in there already.

 

[quick-chat room=”php”]

One Reply to “Hints to help optimise the performance of a PHP website (LAMP)”

Leave a Reply