Duma - Stefano Gombi
Duma - Stefano Gombi

Reputation: 472

Canvas native methods eating lot of RAM

I'm writing a software that can perform operations on HTML5 Canvas based on single pixels. Basically I'm getting all the pixels, updating the values of RGB and writing them back using native methods getImageData, createImageData and putImageData.

While doing some tests I've found that my software uses a lot of RAM, much more than the quantity used by javascript. So I've created this github repo to remove one by one every element that can cause memory consumption and I've found that it was caused by these native methods. I know this software can be improved a lot, but this does not explain this effect. Take it as an example.

You can see the effects of the RAM consumption by changing to different commits: the first is the worst, the second-last the best. By navitaging the different commits you can see that the only version where the used memory seems "explainable" is this commit, where I've removed all the references to canvas native methods.

The intresting thing is that the memory used is not catched by the memory profiler: it's like there's some memory used by chrome not dependent by my javascript. Try running this commit and see amount of memory with your local task manager (htop, for instance) and the google debug tools, js heap voice. There's a huge difference.

All this tests are done on Chrome 47; Firefox seems to does't have this problem.

Is this normal or am I doing something wrong? Why every call of these methods don't release the memory but continue accumulating, generating a memory leak?

Upvotes: 2

Views: 630

Answers (1)

Joseph
Joseph

Reputation: 119837

The preferred answer for this one is to pull out a profiler and check.

Now eyeballing your code, I see this:

pixels.forEach(function(pixel) {
  var interval = 1, x, y, square=[];
  for (x=-interval; x<interval; x++)
    for (y=-interval; y<interval; y++) {
      var tmp = getPixel(pixel.x + x, pixel.y + y);
      if (tmp) square.push(tmp);
    }
});

For each pixel, it's creating an array square. There's your memory hog right there. As the number of pixels grow, you create the same amount of arrays. I'm not sure where square is being used. It's just accepting values.

Additionally, you have a 3-level loop there. And we all know forEach is slower than your regular loop. You might want to change your logic to avoid this.

As for when the GC kicks in, that depends on the browser. You can't really tell when it kicks in, but you can certainly avoid it by keeping an eye on how you create stuff like objects.

Upvotes: 1

Related Questions