SVG vs Canvas Performance

My honours project this year requires the use of graphical browser technologies to produce a modern network weather map.

I have used SVG and HTML5 canvas in the past and have had mixed performance experiences with them. Over summer I had to make use of SVG to draw a traceroute tree-map which in practice performed a lot quicker running on Google Chrome opposed to Firefox.

I wanted to get a clear picture of the current position that both of these technologies are at in terms of performance for drawing and translating large numbers of nodes.

A quick search around the internet showed a handful of existing tests, but I thought I would give it a go to for the practice.

My testing platforms were:

PC
Windows 7
Intel Core 2 Quad 2.6GHZ
4GB Ram

Mac Book Pro
Mac OS Snow Leopard 10.6.7
Intel i5 2.3 GHz dual core
8GB Ram

I tested the following browsers:

  • Chrome 10.0.648.204
  • Firefox 3.3.16 (I didn’t test FF4.0 but I hear performance is not a lot better)
  • Safari 5.0.4

Test Setup / Method

I wrote a simple script that creates/draws a given number of nodes using either ‘svg’ or ‘canvas’. The nodes are then translated as many times as possible per second.

The framerate is calculated by incrementing a counter ever time all of the nodes have been redraw(canvas)/translated(svg) and then outputting its value after each second via a setInterval function.

function draw() {
    if (diffTime >= 1000) {
        fps = frameCount;
        frameCount = 0.0;
        lastTime = nowTime;

        // draw the 'fps' to the window
    }

    // draw some magical particles

    frameCount++;
}

See the full code here: https://github.com/oughton/Drawing-Browser-Benchmark

There are disadvantages/naiveness to this method. I am only testing translation performance of SVG and redrawing performance of canvas. Event support in SVG is a given and is quick due to DOM nodes existing for each node that is drawn. Canvas requires an event system to be built around the application to get the same event support.

But, nonetheless it gives a good overview of where browsers are at.

Results

I took a serious of measurements at various different numbers of particles and recorded the framerate at that value. This produced a big table of numbers but I will just summaries those in 2 pretty graphs.

These results show Chrome as a clear winner for bothCanvas and SVG performance on my windows 7 pc. The SVG performance on both pc and mac degrades significantly as the number of nodes increase across all of the browsers I tested. Chrome and Safari maintained a somewhat usable performance for SVG around the 1000 node mark where as Firefox began locking up.

Another interesting point is Safaris apparent 90 frames / second limit for canvas. While it did not go over 90 frames /second on my mac, it remained mostly constant over the 2000 particles tested.

From these results it appears that reasonable SVG performance is currently possible, but if you are needing thousands of nodes in your visualization, I would stick with Canvas and implement a basic event system.

** UPDATE **

It was requested that I show results for IE 9 due to the addition of hardware rendering support. I actually did these tests before handing in my final project so it is easy to include the new graph here.

The graph shows that IE 9 canvas rendering speed outperforms all other browsers. IE 9 SVG performance still shows the same rapid decline as the number of particles increase.

Trademe & Christchurch Wordle

I wanted to give the trademe API a go. With the recent Christchurch earthquake happening, I thought – why not make a wordle of the the Christchurch related title words?

I was rather impressed with the simplicty of using the API as a guest. You are limited to 50 requests per IP address, per hour. This was enough for me as I only searched through 40 pages to extract title key words.

Setting up an application looked a lot less straight forward, but would be required to dramatically increase this limit.

Here is the code I used to print out all of the titles to the browser (php happened to be most available at the time):

List as $auction) {
    echo $auction->Title . " ";
  }
}
?>

Then is was simply a matter of copying and pasting the output into wordle’s create page. I removed christchurch from the word list so that it did not blow the word cloud out of proportions.

Here it is.

Summer sun – PHP gripes

Summer is almost here. Sunny skies, warm beaches, walks to the bakery for lunch.

Nothing to complain about there.

However, there is something to complain about in php. I was trying to track down a bug in my php scripts at work today and I came across another php pitfall for the weary programmer.

I think my svn commit change log will best explain what tripped me up.

The red line shows the bug in my old code, where I forgot a dollar sign and misspelled the variable ‘$direction’.

This was not producing a syntax error but rather the ‘direcion’ was being taken as a string and multiplied by -1 in some way, shape or form.

A small amount of googling came up with someone who also experienced a similar problem:

http://www.php.net/manual/en/language.types.string.php#89757

1D Clustering Problem

I have been given a large amount of anomaly annotations that goes along with a set of internet trace data.

Here is a quick scatter plot I whipped up to get an overall idea amount and spread of data that I am dealing with.

Each of the ticks of the yaxis correspond to a snort id (see http://www.snortid.com). Time is along the xaxis and covers just under 2 minutes.

It is not appropriate here to display all of this data as event icons on top of the graph. This is only showing 2 minutes of data and the ability to zoom out to view days worth at a time is also required.

In order to effectively visualise this I am going to have to look into 1-dimensional clustering algorithms. This would allow for events which occur with small amounts of relative variation to be aggregated into one graph event summary.

Now, there are quite different cluster patterns for each of the snort ID’s so I am not sure how successful I am going to be.

Sparklines using Flot

A friend from university sent me a link to a article about ‘sparklines’. As the article title states, sparklines are intense, simple, word-sized graphics.

The article:
http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR

This visualisation style fits in well with one of the projects I am working with that displays a 2D matrix of latencies between national servers. Currently it displays a single latency value (the mean RTT) inside each cell. It would be nice if a sparkline could be placed in each of the cells to give a summary of the last two hours of latency data.

The current system in place makes use of the Flot graphing library for producing graphs so I thought I would give sparklines a go using that.

It turned out to be rather straightforward. Here is the final result:

What I did:

  1. Turned off the grid – gets rid of all borders, grid lines, ticks and tick labels.
  2. Made a series with one data point equal to the last datapoint of the main series – a trick to colour the last point red.
  3. Set the max x axis option to 1 unit more than the max datapoint – stops the red point from getting cut off.
  4. Draw the graph with the options and series.
$(document).ready(function(){
var data = [ [0, 1], [1, 2], [2, 2], [3, 2], [4, 2], [5, 3], [6, 4], [7, 2], [8, 2], [9, 3], [10, 5], [11, 5], [12, 4] ];

  var options = {
    xaxis: {
      // extend graph to fit the last point
      max: data[data.length - 1][0] + 1
    },
    grid: {
      show: false
    }
  };

  // main series
  var series = [{
    data: data,
    color: '#000000',
    lines: {
      lineWidth: 0.8
    },
    shadowSize: 0
  }];

  // colour the last point red.
  series.push({
    data: [ data[data.length - 1] ],
    points: {
     show: true,
     radius: 1,
     fillColor: '#ff0000'
    },
    color: '#ff0000'
  });

  // draw the sparkline
  var plot = $.plot('#container', series, options);
});

Scalable div appending

Ridiculously Slow – being silly

for (var i = 0; i < 65000; i++) {
  document.body.appendTo(document.createElement("div"));
}

Fast – using a DocumentFragment

var fragment = document.createDocumentFragment();

for (var i = 0; i < 65000; i++) {
  fragment.appendChild(document.createElement("div"));
}

document.body.appendChild(fragment);

Probably obvious for most, but not for me on a Friday evening after working all day. 😛

Clickable event support for Flot

I am in the process of developing a plugin for ‘Flot’ – the pure Javascript plotting library for jQuery.

The plugin needs to add functionality to Flot that allows clickable (or hoverable) events to be overlaid on the graph. An event is a certain occurrence that occurs at a specific time or range of time.

This is what I have so far:

The event pins and tooltip currently are divs overlaid on flot’s div after it has been drawn. JQuery UI has a nice bounce feature that lets you bounce the red pins as a one liner:

$('#someDiv').effect("bounce", { times:3 }, 300);

This bounces ‘someDiv’ 3 times in the period of 300ms. I came across an issue with firefox using this code. When the div finishes bouncing, the ‘mouseenter’ and ‘mouseover’ events are again triggered. This leads to the bounce animation being repeated if you place this code inside a mouse over event as I did. Interestingly enough, this does not happen in Chrome and Safari.

Here is the workaround I used for firefox.

div.hover(
   // mouseenter
   function () {
      // check if the mouse is not already over the event
      if ($(this).data("bouncing") == false ||
          $(this).data("bouncing") == undefined) {

          // check the div is not already bouncing
            $(this).effect("bounce", { times:3 }, 300);
            $(this).data("bouncing", true);
      }
    },
    // mouseleave
    function () {
      $(this).data("bouncing", false);
    }
);

Oh the joys of cross browser support.

This is working well so far. The problem is that I need some way of visualizing many more events on the same size graph. I am not sure how I will tackle this yet. I have set up a hierarchical structure to allow only events of specific importance to be shown at one point in time. I need to reduce the size of the red pins, or more likely, look at a different way of visualizing the events.