This animation makes my fans spin up after several seconds, and it seems to have a sub-par framerate. I am trying to understand why, and optimize its performance.


The animation function (this is the main part of the code):

function animate() {
    ctx.clearRect(0, 0, c.width, c.height);

    for (var i = 40; i < max; i+= 60) {
        var radius = Math.floor(i+Math.sin(t/10)*10)
        ctx.arc(center[0], center[1], radius, 0, 2 * Math.PI, false)


The for loop draws the minimum number of circles needed in order to fill the screen. Their radius pulses in and out with a sine function based on the 't' variable.

Am I doing something wrong?

  • 2
    \$\begingroup\$ Welcome to Code Review! Do you suspect something is wrong or are you just looking for general improvements? \$\endgroup\$
    – Mast
    Commented Sep 9, 2015 at 23:38
  • \$\begingroup\$ @Mast Thanks! I guess I'm just assuming that it's inefficient because it makes my macbook's fans spin up after maybe 10 seconds, whereas I've seen fullscreen canvas animations/apps that take basically no noticeable toll on my computer. \$\endgroup\$ Commented Sep 9, 2015 at 23:40

1 Answer 1


I guess I'm just assuming that it's inefficient because it makes my macbook's fans spin up after maybe 10 seconds

That's not really a good measure of "efficiency". The browser is trying to render 60 frames per second. That's a frame every ~16ms. Of course that's going to cause your processor to churn.


You can use <number> | 0 to trim off the decimal places of your numbers. In some JS engines and certain versions of JS engines, bitwise operations are faster than your regular math functions.

2 * Math.PI

There is a very small penalty when accessing object properties and becomes evident when you use it all over the place. Since Math.PI is a constant value, it wouldn't hurt if you assigned it to a variable for direct access. In fact, 2 * Math.PI is also constant. Why not put the result in a variable and spare the engine a multiplication operation as well.

function animate() {

The issue with depending on just the render loop is the time it takes between updates. requestAnimationFrame can run faster or slower depending on conditions. If your "tweening" is time-sensitive, you might want to update based on delta-time instead.

  • \$\begingroup\$ Thank you for the insight. I did some research, and after recreating it in a webGL renderer (Pixi.js), it runs without breaking a sweat. I think it's just a limitation of the 2d canvas context… \$\endgroup\$ Commented Sep 10, 2015 at 1:51
  • \$\begingroup\$ @MarcusPlimsoll That's because webgl is hardware accelerated. \$\endgroup\$
    – Joseph
    Commented Sep 10, 2015 at 2:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.