roro
roro

Reputation: 213

HTML5 Canvas memory leak performance issue

I have 2 canvas elements, and I draw them in an interval of 125ms.

Both of them must be completely redrawn due to the nature of their work, so it's not possible to re-draw only certain parts of them to increase performance.

Problem

When I see in the task manager, the Working Set (Memory) is constantly increasing, based on how fast I'm re-drawing the canvases.

What I have tried so far

  1. Use clearRect for cleaning (as opposed to set it's width again)

  2. Tried deleting the parent div of canvas and recreating the div and loading canvas again in it : This helps slow the the memory increase, but doesn't completely stop it.

  3. Reduced different context.fills to as few as possible, but again due to nature of the canvas, it still has a lot of those.

Even if I do all of these things, the Working Set can be high, but shouldn't be constantly increasing.

Any suggestions how to control the memory leak?


Update: The leak isn't in the canvas drawings. I'm using a web-worker to pass on data to the canvas, which is leaking somewhere. Sorry about the confusion!

Upvotes: 1

Views: 2784

Answers (2)

wolfhammer
wolfhammer

Reputation: 2661

Try wrapping your animation loop in another function that initializes the variables. This way no variables are created or destroyed in the loop.

var aniTimeout = null;

function wrap() {
  
  var can = document.getElementById('can');
  var ctx = can.getContext('2d');
  var x = 0;
  var y = 0;
  var r = 5;
  var colors = ["#FF0000","#009900","#0000FF","#990099","#00CCCC","#FFCC00"];
  var cLen = colors.length;
  var ms = 125;
  
  function ani() {
    ctx.clearRect(0,0,50,200);
    ctx.clearRect(0,0,200,50);
    ctx.clearRect(150,0,200,150);
    ctx.clearRect(0,100,200,150);
    x = Math.floor(Math.random() * 190) + 5;
    y = Math.floor(Math.random() * 140) + 5;
    ctx.fillStyle = colors[Math.floor(Math.random() * cLen)];
    ctx.beginPath();
    ctx.moveTo(x, y);
    ctx.arc(x,y,r,0,Math.PI*2);
    ctx.fill();
    aniTimeout = setTimeout(ani,ms);
  }
  
  ani();
  
}

wrap();
#can {
  border:1px solid #999999;
}
<canvas id="can" width="200" height="150"></canvas>

Upvotes: 0

Drew Dahlman
Drew Dahlman

Reputation: 4972

Using clearRect is your best bet.

Why are you using a 125ms redraw vs requestAnimationFrame ( this uses the native tick, which will also allow for dropping frames and help with performance )

I would avoid removing DOM elements as that is pretty costly.

Memory is always going to go up, I would also check your closures as anything that isn't in a closure will not be auto garbage collected thus leading to more memory use.

Checkout to statsjs which will tell you your FPS and give you something to graph against. also Memory Stats which will show you memory consumption.

My guess as to why you're seeing such a spike is that resources aren't being garbage collected and your code could use some optimizations, but without seeing anything that is a big shot in the dark.

Upvotes: 4

Related Questions