February 1, 2008

Is server or client processing better for charts and graphs?

Author: Colin Beckingham

Webmasters are frequently required to serve up charts and graphs to clients. Part of the planning for such images involves a decision about whether to process the chart on the server or at the client end. Of course, it depends on the circumstances. There are costs and benefits to both approaches.

The generation of a chart at the server involves the creation of an image such as a .png file and then displaying this file as part of the delivered page. Prior to the image creation a script must set up the data points and the axis labels, switch on colours, create a legend, size the picture, and send it out.

Client-side processing sends the parameters and data points for processing by the client, often with JavaScript. However, actual delivery of the page involves sending not only the data and parameters, but also the required JavaScript and cascading stylesheet libraries to draw the final chart. The following table compares the two approaches.

Summary Comparison Server side Client side Advantages Disadvantages
  • Data remains confidential
  • Chart can be copied and pasted as a separate unit
  • If multiple copies of the chart are required, the image can be easily repeated
  • Browser may be able to resize the image
  • Images load progressively, visibly in the browser
  • Data is available locally for reprocessing
  • Once the .js and .css libraries are downloaded they can be re-used with no further download overhead
  • Identical data cannot be reprocessed without refreshing the page
  • Heavier load on the server processor
  • Server side image storage required
  • Multiple identical images need to be separately drawn
  • .js and .css libraries need to be part of the download package
  • JavaScript must be available and activated on the client
  • Taking a copy of a chart requires a screenshot
  • Libraries load without screen activity, giving the appearance of slow loading

The open source world offers class libraries to provide either or both solutions. An example of a simple server-side library is libchart, and a client side library is Webfx Charting, both of which can be incorporated into a PHP script. Both projects provide samples of library output and example code. Each method probably requires approximately the same amount of coding effort. This article is not intended to compare the output of the two libraries, just to examine the relative advantages and disadvantages of the two approaches. Additionally, there are other methods such as Java which are not considered here.

The choice for webmasters comes down to two major components: the actual processing time, and the bandwidth required to deliver the final product. Generally the bandwidth component is easier to quantify. Some server managers place official quotas on bandwidth, but leave unofficial honour system quotas on processing time, reserving the right to reduce service to webmasters who place unfair burdens on processing time on shared servers. It is in the interests of webmasters to keep the server managers happy on both counts.

Download size

Focusing on the code necessary to draw the chart on the client machine, in the server side situation the code can be very short:

<img src='mypic.png'/>

In the client side situation the minimum might be:

<script type="text/javascript" src="../includes/excanvas.js"></script>
<script type="text/javascript" src="../includes/chart.js"></script>
<script type="text/javascript" src="../includes/iecanvas.js"></script>
<script type="text/javascript" src="../includes/canvaschartpainter.js"></script>
<link rel="stylesheet" type="text/css" href="../includes/canvaschart.css" />
</head><body onload="ieCanvasInit('../includes/iecanvas.htc');">
<div id="chart1" class="chart" style="width: 1000px; height: 250px;"></div>
<script type="text/javascript">
function draw1() {
var c = new Chart(document.getElementById('chart1'));
c.setDefaultType(CHART_LINE);
c.setGridDensity(10,10);
c.setVerticalRange(-5131,66880);
c.setHorizontalLabels([JS array of labels]);
c.add('Current production','#4040FF',[JS array of data points]);
c.draw();
}
</script>
<script type="text/javascript">
window.onload = function() {
draw1();
}</script>

That's more than 800 characters, not counting spaces or data, about 450 of which is repeated for each chart to be displayed. Compared with 22 characters for the server side, that's not so trivial.

When it comes to data, the client-side is expecting an array of numbers. In the case that the array is short and consists of simple integers, the array is short and almost trivial. Now consider that the data might be an array of double-precision numbers such as [123456.7890,123456.7889,...,2.6]. A webmaster might be able to round down to integers before transmission, but this would lose some precision, which could be a problem when the data is to be re-used at the client end. Two hundred data points at 11 characters per number each plus the separation character gives an array character length of about 2,400.

In the case of one single chart we can expect something like:

Server side (bytes) Client side (bytes) Total Total
Basic html 22 Basic html 400
Libraries 0 Libraries (loaded once per page, if not cached) 66,000
Image 25,000 Image code 450
Data 0 Data (est., per image) 2,400
25,02269,250

So the download for the client side will probably be larger for one image.

Now consider the case of five different charts on the same page:

Server side (bytes) Client side (bytes) Total Total
Basic html 100 Basic html 400
Libraries 0 Libraries (loaded once per page, if not cached) 66,000
Image 125,000 Image code 2,250
Data 0 Data (est., 5 images) 12,000
125,10080,650

In the case of five charts, the client side download package is smaller. Clearly the issue of the size of the download depends entirely on the number of charts. While these numbers may appear insignificant, when a page is served up many thousands of times, the total becomes a threat to your bandwidth limit.

CPU load

Next we need to consider the issue of CPU load. The server-side class library uses the freetype and gd libraries. Some server managers consider these libraries to be processor-intensive, a critical issue in a shared server environment. You would expect that server-side processing would create a greater CPU load, but is that really so?

Using the top utility on a standalone single-processor server (2.8GHz Intel with hyperthreading and 2GB of RAM) I had the following experience. I set up a PHP script to generate a chart from 200 random data points using MySQL. One script output the charts as three separate 28KB .png images and the other drew three charts with JavaScript. Some of the CPU load can be attributed to MySQL, but since the database processing for each is the same, this should cancel out.

Results GD -> .png JavaScript
Page load seconds (*dialup) 15 3
CPU load Average increase of 10% for ~5 seconds Average increase of 3% for ~3 seconds
Download size (Source code + Other) 28K * 3 = 84K 8K + 66K = 74K

Conclusion

In summary, charting and graphing are important and informative assets. After all, a picture can be worth a thousand words. However, in a Web context, we need to balance whether it is better to send charts and graphs as pictures or the thousand words. Providing the data and then using JavaScript locally to draw the results not only gives a faster page load to the end user, but reduces the load on the server CPU, in this case by a factor of about three.

Categories:

  • Internet & WWW
  • Graphics & Multimedia