Upgrade to Pro — share decks privately, control downloads, hide ads and more …

High Performance Data Visualizations

High Performance Data Visualizations

If you thought that building rich, interactive and mobile-friendly visualizations of high volume data with 100,000+ points just using the power of browser-side JavaScript was impossible, this talk by the creator of Leaflet will prove you wrong.

We’ll cover every important aspect of achieving peak performance and responsiveness for such kind of apps, including real-time data simplification, computational geometry and clustering algorithms, tree structures, fast collision detection, typed arrays, Web Workers and mixing Canvas with SVG.

Vladimir Agafonkin

April 26, 2013
Tweet

More Decks by Vladimir Agafonkin

Other Decks in Programming

Transcript

  1. var tree = new RTree(); tree.insert( {x: 5, y: 10,

    w: 10, h: 15}, obj); ... tree.search( {x: 7, y: 7, w: 5, h: 5}); github.com/imbcmdth/RTree
  2. importScripts('data.js'); ... onmessage = function (e) { var result =

    searchData(e.data.query); postMessage(result); } Loading in Worker
  3. var array = new Float16Array(len); ... var buffer = array.buffer;

    postMessage(buffer, [buffer]); // buffer stops being available transferable objects (Chrome, Firefox)
  4. function addNumbers(a, b) { 'use asm'; a = a |

    0; // int b = +b; // double return +(a + b); // double } bright future — asm.js
  5. SVG •fast native events for interactivity •easy to update separate

    objects •slows down the browser (with a large number of objects)
  6. Canvas •doesn't affect browser performance after rendering •you can draw

    something once and copy •pixel data can be manipulated or generated in a Worker
  7. WebGL •main way to visualize in 3D •very fast in

    2D if you need to draw lots of sprites •performance gain vs Canvas-2D is questionable in other cases •much more difficult to use; limitations •no support in iOS and IE9-10
  8. function drawStar() { ... return canvas; } var star =

    drawStar(); ctx.drawImage(star, 10, 20); ctx.drawImage(star, 50, 70); ...
  9. function drawLine(x1, x2, y1, y2) { ctx.strokeStyle = 'red'; ctx.beginPath();

    ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); } drawLine(10, 20, 30, 40); drawLine(200, 10, 0, 50); drawLine(30, 40, 70, 0);
  10. function drawLine(x1, x2, y1, y2) { ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2,

    y2); } ctx.strokeStyle = 'red'; drawLine(10, 20, 30, 40); drawLine(200, 10, 0, 50); drawLine(30, 40, 70, 0); ctx.stroke();
  11. var data = ctx.getImageData(0, 0, width, height).data; worker.postMessage(data, [data]); ...

    worker.onmessage = function (e) { var imageData = ctx.createImageData(width, height); imageData.data.set(e.data); ctx.putImageData(imageData, 0, 0); } Canvas + Worker
  12. var pixels = new Uint8ClampedArray( width * height); function drawPixel(x,

    y, r, g, b, a) { var i = 4 * (256 * y + x); pixels[i] = r; pixels[i + 1] = g; pixels[i + 2] = b; pixels[i + 3] = a; } ... postMessage(pixels.buffer, [pixels.buffer]); drawing pixels in a Worker
  13. var pixels = new Uint8ClampedArray(data); for (var x = 0;

    x < width; x++) { for (var y = 0; y < height; y++) { var i = 4 * (256 * y + x); pixels[i] = 2 * pixels[i]; pixels[i + 1] = 2 * pixels[i + 1]; pixels[i + 2] = 2 * pixels[i + 2]; } } ... postMessage(pixels.buffer, [pixels.buffer]); processing pixels in a Worker