Posted on by & filed under Content - Highlights and Reviews, Programming & Development.

codeA guest post by Peter Le Bek. He tweets at @_lebek and writes code at

D3.js is a bit like the C of visualization frameworks. Programmers are often surprised to learn that D3.js doesn’t include high-level charting functions (e.g. plot(), bar(), or line()). Most of the work is left to the programmer, and there are few surprises in the output SVG. It might seem that D3.js code is almost optimized-by-default – it draws what you tell it to draw and nothing else. This isn’t quite true. The low-level nature of the framework means there are usually several ways to do the same thing, each with it’s own performance implication.

In my last post I showed you how to build responsive visualizations with D3.js. In this post I have created a checklist that helps you identify the root causes of slowness in D3.js code, and shows you how to remove the slowness.

Does your code generate many SVG elements?

SVG performance varies across browsers and devices, but they all have their limits. Does your code produce more than several thousand SVG elements? If so, SVG complexity is a possible culprit.

Solution: Remove non-essential elements (e.g. group elements)

Group elements (<g></g>) are useful when a set of elements need to share some properties. We’ve all written code that looks like this:

We could do the same thing without a group element by applying the position attributes to the circle and text directly:

Since render time scales approximately linearly with the number of elements, eliminating the group elements would reduce render time by ~1/3.

Alternative solution: Use a canvas element instead of SVG

If render times are still poor after removing non-essential elements, you might consider using a canvas element instead of SVG. Unlike SVG, canvas performance is determined by the canvas size rather than its contents. Mike Bostock has built a simple example.

Alternative solution: Reduce the size of the data

Sometimes, the only option is to reduce the size of the data. You could:

  • resample the data (e.g. daily average instead of minute-by-minute)
  • cluster the data (e.g. K-means clustering)
  • use a smaller portion of the data (e.g. 1-year instead of 10-year history)

Does your animation loop use setInterval/setTimeout?

The problem with setInterval/setTimeout is that they force you to guess when the browser will be ready to redraw. If the guess is wrong, it can cause stuttering and skipping.

Solution: Use d3.timer

Newer browsers have a built-in API for optimizing animation loops called requestAnimationFrame. Paul Irish wrote a good overview of this. D3.js contains a timer that uses this API when possible, and otherwise falls back to setInterval. d3.timer is almost a drop in replacement for setInterval, so making this change should be very simple:

Does your animation loop redraw elements that haven’t changed?

When the time comes to animate a static visualization, it’s tempting to lump all of the draw code into an update function and call it with new data on each iteration of the animation loop. It’s a waste of draw time if some of these elements don’t change frame-to-frame. Common examples of this would be axes and legends.

Solution: Update selectively

Everything static can be drawn before animation begins, then the update function only needs to draw elements that change. The best way to update a visualization with new data is by using the update pattern.

Are you polling the server for updated data?

Sometimes performance issues exist on the network side. Realtime charts fetch their data from the server at regular intervals. If the amount of data sent back is significant, it can impact the smoothness of the update.

Solution: Fetch data incrementally

Cubism.js, a popular timeseries visualization library, is able to handle large streams of data because it fetches only the most recent data on each update. The library itself is actually a fantastic example of the techniques described in this post (incremental update, optimized animation, and use of canvas elements).

Debugging D3.js Performance Issues

Chrome DevTools make it easy to dig deeper when the checklist above doesn’t help. The most useful section is under Timeline > Frames. According to the DevTools documentation:

“A frame represents the work the browser must do to render a single frame of content to the display.”

This is exactly what we need. We can use it to answer questions like:

  • Which render tasks take the longest?
  • Is there too much work in the animation loop?
  • Is a canvas element faster than SVG?
  • Are server response times limiting performance?

Here’s a quick example using a screenshot of the timeline for a Cubism.js demo:


The Timer Fired record (about halfway down in the demo) is key to understanding this data. It represents the start (and end) of an iteration of the data update loop. It’s clear that all of the draw events fit well within the update window. If draw events were still taking place at the next timer event, we’d expect to experience stuttering.


This was a quick overview of a topic that really goes quite deep covering D3.js. The usual advice applies: don’t optimize prematurely – optimize the easy stuff first – and always consider which browsers and devices your code will run on.

Look below for some great D3.js books from Safari.

Not a subscriber? Sign up for a free trial.

Safari has the content you need

Interactive Data Visualization for the Web shows you how to create and publish your own interactive data visualization projects on the Web – even if you have little or no experience with data visualization or web development. It’s easy and fun with this practical, hands-on introduction. Author Scott Murray teaches you the fundamental concepts and methods of D3, a JavaScript library that lets you express data visually in a web browser.
Developing a D3.js Edge is aimed at intermediate D3.js developers, so to get the most from this book you need to know some JavaScript, and you should have experience creating graphics using D3. You will also want to have a good debugger handy (Chrome Developer panel or the Firefox/Firebug combo), to help you step through the many real world examples that you’ll find in this book.
Data Visualization with d3.js walks you through 20 examples. You can finally stop struggling to piece together examples you’ve found online. With this book, you will learn enough of the core concepts to conceive of and build your own visualizations from scratch.
It begins with the basics of putting lines on the screen, and builds on this foundation all the way to creating interactive animated visualizations using d3.js layouts.
Visual Storytelling with D3: An Introduction to Data Visualization in JavaScript provides readers with a strong framework of principles for making well-conceived and well-crafted infographics, as well as detailed and practical instructions for how to really wield D3, the best tool for making web infographics available. An extended example is used in the book to explain how to put theory to practical use.

Tags: C#, Canvas, Cubism.js, D3.js, d3.timer, resample data, speed, SVG, visualization,

Comments are closed.