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

High Performance Data Visualizaitons in JavaScript [Topconf 2013]

High Performance Data Visualizaitons in JavaScript [Topconf 2013]

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 will prove you wrong.

We’ll review every important aspect of achieving peak performance and responsiveness for these types of applications, including search indexes and tree structures, computational geometry and clustering algorithms, real-time data simplification, fast collision detection, advanced use of Web Workers and mixing Canvas with SVG and HTML.

Vladimir Agafonkin

November 06, 2013
Tweet

More Decks by Vladimir Agafonkin

Other Decks in Technology

Transcript

  1. var tree = rbush(); ! tree.insert([5, 10, 15, 25, obj]);

    ! ... ! tree.search([7, 7, 12, 12]); github.com/mourner/rbush
  2. •avoids rendering many objects in the same spot •free index

    for instant mouse/touch interaction greedy rendering
  3. Worker •isolated DOM-less environment, freaking fast •runs in its own

    thread, doesn’t lock the UI •sends and receives messages
  4. importScripts('data.js'); ! ... ! onmessage = function (e) { var

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

    array.buffer; ! postMessage(buffer, [buffer]); ! // buffer stops being available transferable objects (all browsers except IE)
  6. UI Worker JS browser doesn't freeze,  data is sent

    as ArrayBuffer data loading UI UI
  7. function addNumbers(a, b) { 'use asm'; ! a = a

    | 0; // int b = +b; // double ! return +(a + b); // double } asm.js
  8. SVG •fast native events for interactivity •easy to update separate

    objects •easy to animate •slows down the browser (with a large number of objects)
  9. 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
  10. 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, difficult in IE11
  11. low number of objects:  use SVG ! lots of

    stuff to draw:  use Canvas
  12. function drawStar() { ... return canvas; } ! var star

    = drawStar(); ! ctx.drawImage(star, 10, 20); ctx.drawImage(star, 50, 70); ...
  13. 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);
  14. 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();
  15. var data =  ctx.getImageData(0, 0, width, height).data; ! worker.postMessage(data.buffer,

    [data.buffer]); ! ... ! worker.onmessage = function (e) { var imageData =  ctx.createImageData(width, height); ! imageData.data.set(e.data); ! ctx.putImageData(imageData, 0, 0); } Canvas + Worker
  16. 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
  17. 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