Improving the performance of your charts

Although performance is excellent, (eg compared to server based charts libraries), you may still want to tune RGraph further. The biggest thing you can do is use HTTP compression, which reduces the initial download time of the libraries, but there are a number of things you can do:

  • Compression
    HTTP compression can dramatically reduce your bandwidth bills and increase the speed of your website. The RGraph.common.core.js file for example used to be over 100k, but with compression this was reduced to around 17k. Less than a fifth of the original size! If you do only one thing to aid performance, then it should be this.

    To achieve this with Apache you have a few options:

    • You can use this Apache 2 directive that compresses output:
      AddOutputFilterByType DEFLATE text/html text/plain application/x-javascript application/javascript text/css
    • You can use the Apache 1.3 module mod_gzip which compresses the libraries on the fly.
    • You can compress the libraries manually using the Unix gzip command, rename them to remove the .gz suffix and add the header using an Apache directive (eg AddEncoding gzip .js). If you have some sort of release process/script, it would make sense to add this to it to automate the procedure.

  • Minification
    Minification reduces the size of the library before compression takes effect, removing unnecessary spaces and comments etc. A combination of minification and compression will give superb results. For example, before being split up into seperate files, minification combined with compression reduced the common library from over 100k to roughly 10k (!). There is a Unix C program (jsmin) which minifies JavaScript libraries in the download archive.

    You can get pre-minified versions of the latest stable libraries here.

  • Pre-emptive caching
    Slightly different to caching itself, is pre-emptive caching. This involves downloading the libraries before the page that requires them is shown. This way, they're already in the users browser cache and the chart will subsequently appear to be much much quicker. An example of this would be having the library included at the bottom of your index page of your website (optionally with the defer="defer" attribute). The script can be downloaded at will because the page doesn't actually use it, but for subsequent pages it will already be in the users browser cache.

  • Caching
    Since the libraries you're using won't change that often, you can set distant Expires: headers on them, or appropriate Cache-Control: headers, and the client will not even have to contact your server for it. When you want to make sure the library is re-downloaded (eg. you update the library), then simply change the filename.

  • Script tag placement
    According to Yahoo! guidelines placing the <SCRIPT> tag at the bottom of the page can increase the percieved load time. If you do this, then your charts should be created in the window.onload or the jQuery ready events, otherwise the browser may try to create them without the library having been loaded, and will therefore subsequently fail.

    You should consider the effect that the window.onload event has when your page is rather weighty. If the page is weighty there will be a small delay before the onload event fires, and therefore creates the chart(s). This might not be so bad if the chart is not immediately visible, however if it is then you should carefully consider using the onload event. You may wish to load the library in the page header, define the canvas tag and then immediately define the javascript that creates the charts. This way the charts will be created and shown, and then the rest of the page loads. The end result is that your charts appear to be faster.

    The jquery ready event makes use of the DOMContentLoaded event if it's available. This event fires when the page has finished loading the HTML and script, but doesn't wait for the images and CSS. It therefore can be faster (sometimes very noticably) than the window.onload event. An example of it's use is:

    <script>
        $(document).ready(function ()
        {
            // Create your chart here
        });
    </script>
    

    Between the onload event, the jQuery ready event, asychronous Javascript and careful tag placement, you will need to experiment to get the right result for you.

  • Document structure
    The structure of your document can have a significant impact on how fast your charts are displayed. If, for example, you use tables for layout, this can delay the display of elements that are affected by the size of the table. Where possible, you should consider trying to convert your layout to DIVs. An example of this is the front page of this website. The example charts were right aligned using a table as a container. This caused a visible delay when showing them. In this case it was a simple matter to convert the page to use DIVs, and the page subsequently displays much faster.

  • Creating your charts asynchronously
    Where possible, you may wish to create your charts asynchronously. This allows the browser to continue rendering the page immediately after getting to the code that creates the chart. This might not be perceptible if you don't have a lot of charts, or your page is small. You can read a little more about asynchronus charts and see example code here.

    Note that some versions of different web browsers have had issue with creating charts asynchronously, which presents itself by not drawing text sometimes (it's not consistent). Simply not using asynchronous chart production in this case resolves the issue.

  • DOMContentLoaded event
    Using this event can speed up the display of your charts significantly compared to the more well known window.onload event. It is supported by Chrome, Gecko based browsers (ie Firefox), Safari, Opera and Internet Explorer 9+. This event fires when the structure of the page is loaded, but not necessarily the images or CSS. This means that if your page is laden with images, this event will fire before the onload event, thus creating your charts quicker. The effect can be very noticeable.
    document.addEventListener('DOMContentLoaded', function ()
    {
        // Create chart here
    }, false);
    
    You can read more about the DOMContentLoaded event on the Mozilla site, here. There's an example of the DOMContentLoaded event here.

  • AJAX requests
    If you can take advantage of AJAX, you can use this method to retrieve data from your server. If, for example, you have a chart that shows ongoing information, instead of simply refreshing the entire page, you could use an AJAX request to just retrieve the data that you want and update the chart that way. This reduces the amount of data needed to be transferred, thus reducing the bandwidth used, and will be quicker than a full page refresh, particularly if your page is weighty. There's a simple AJAX function that you can use here or you can use the jQuery $.get() or $.ajax() functions.

  • Combining libraries (HTTP 1.1 only)
    You may wish to consider combining the RGraph libraries into a single file. This won't save on the size of the individual libraries, but will save on the headers that are sent as part of the response. If a typical response sends 500 bytes worth of headers, and you send four chart libraries, then combining the libraries would save 1500 bytes. Multiple factors need to be considered though, including things like caching, which can circumvent the unneccessary repeated downloading of the libraries.

    To make your life straight-forward, you may want to make this a part of your release script/process. This way you can make changes to the scripts in your development environment as you would normally.

    Another effect of combining libraries is reducing the amount of HTTP connections needed to retrieve them. Most browsers have a limit on how many connections they can create simultaneously, so if they're not being used to retrieve your chart libraries, they can be used for something else.

    There is a PHP script that you can use to combine multiple Javascript files into one file here: combine.php And you would use it like this:

    <script src="/javascript/combine.php/RGraph.common.core.js/RGraph.common. ... "><script>

    Note about HTTP2

    This kind of combining JavaScript libraries (and CSS files too for that matter) has become an anti-pattern in HTTP2. What this means is that if you're using HTTP2 then there's no need to combine libraries in this way. Combining libraries saves on using multiple connections and HTTP2 only uses a single connection. So there's no saving in doing this. Indeed if two pages use a slightly different combination of libraries then libraries that have already been cached may not be able to be reused - thus creating extra downloads.

  • Avoiding or minimizing shadow blur with animations or large charts
    If you're using animations then you may wish to avoid or reduce the shadow blur that you're using. With HTML5 canvas shadow blur is a drain on performance - so if you're looking to get the most out of your charts or are using animations which require redrawing the chart, turning off the shadow blur can reduce the time it takes to draw the charts leading to smoother charts.

  • Clearing the canvas before drawing
    By clearing the canvas to a solid color your computer can make optimisations that it can't do if you leave it at the default transparent color. This improvement can be subtle - so you won't always see a difference. You can do this like so:
    .on('beforedraw', function (obj)
    {
        RGraph.clear(obj.canvas, 'white');
    })
    

 

A reasonable performance strategy

Although there's a lot you can do in regards to performance, a few of the points here will suffice for most websites:

  • Compression
  • Minification
  • Pre-emptive caching
  • Caching
The number one thing you should do is compress your libraries. This has multiple benefits and provides by far the most gain, effectively for free. Secondly, use the minified libraries. Since you can download the minified libraries here, you might as well use them. Then we have pre-emptive caching. Since most websites won't show charts on the front page or will have a login page that is shown before any charts, this effectively eliminates the charts library download. And lastly caching should be done as a matter of course. There's no reason to keep downloading the same library so even caching for only 30 minutes (or the duration of an average visit to your website) will produce results.

 

General website performance tools

If your aim is to improve your websites performance as a whole then you may be interested in these tools:

Note about performance and HTTP/2

As of 2016 HTTP/2 will become more widespread - with many people planning to make the switch to it - and this includes many hosting providers. Patterns such as domain sharding (using multiple hostnames) and concatenating your JavaScript libraries together become anti-patterns and are less useful and in some cases actually hurt performance. If you're planning to switch to HTTP/2 or already have then you should compare the advantages of some of these techiques versus not using them and determine what, if any, the benefit is. Again, in some cases the use of some of these techniques may not help at all and may even hurt performance.