Canvases and timers

Recently, I have discovered a site that uses multiple canvas elements on a page to animate different behaviors. The animations started as soon as I have scrolled to the corresponding canvas element, and the more I scrolled, the more animations were started. Of course, most of them remained off screen, but I could still feel their effect on the scrolling experience. It was interesting to me why this happened, because the canvas element in itself allows for very fast and smooth animations and requestAnimationFrame proves it. So I opened Chrome Developer Tools and recorded what was happening. When I went to the memory tab, I saw the following sawtooth pattern:

Memory footprint on a site using canvases and timers

During the animations, memory usage increased slowly, but steadily while I was doing absolutely nothing. When it reached 21.1MB I stopped the recording, because it was clear what would happen. This could be one reason why the site slowed down the longer I stayed on it.

Here are the individual frames:

Individual frames during the use of the site

We can see that on my machine even 30fps were impossible to achieve. Instead of 16ms per frame, the average frame shown here takes around 300ms. The bars are mostly yellow, which indicates heavy processing with the help of JavaScript. Here is what is happening in part of the selection:

Performance problem areas in the site

I have expanded two of the bars to see more clearly what is happening. They both have shown that a timer is fired repeatedly on line 3917 in the file processing.js. These timers collectively add a lot of computational overhead and slowed down the animations in the canvas elements. The more elements we have, the more cautious we need to be with how efficiently these animations are performed as this example illustrates. RequestAnimationFrame can be used instead of timers here.

We also need to question whether it is a good idea that animations are triggered automatically. In most cases, it's better to leave the user decide which one he wants to see as he probably won't be interested in all of them. The ability to stop the animation that is currently playing allows for more efficient use of the browser resources. Playing only one animation at a time ensures that the user isn't distracted from the other content of the site. But all this means that animations must be connected in a common mechanism.

As we can see, it is not the canvas element that is the problem, but rather how we use it. Even given a good technology, we may still misuse it. Checking how our creations respond in use allows us to see problem areas before they reach the user.