7
votes

I've got a WebGL application that manages a lot of data. I've run into issues on IE11 in which it quickly runs out of memory (Chrome and FF do not exhibit this issue). However, when I created some test code to isolate the cause of the leak, the test code leaks on Chrome as well. Further testing showed that even Chrome is leaking in the actual application, or appears to, but seems not to crash as IE11 does.

Here is a fiddle of the test code that exhibits the problem: EXAMPLE

Basically, I'm creating buffers using this:

var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, bufferData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);

For each buffer that I create, I also make a corresponding call to delete it like this (deleted when necessary):

gl.deleteBuffer(buffer);

However, as can be seen in the jsfiddle test code, deleting the buffer(s) seems not to free the memory used by the browser. It will quickly run out of memory even though the buffers are getting deleted.

This is a contrived example, obviously, but it does reflect what I'm doing (i.e., creating buffers and later deleting them), but over time it seems this causes memory not to be freed.

How should I be freeing this memory to avoid a leak? Any ideas?

2
This seems like a bug in Chrome. Filed one here - gman

2 Answers

0
votes

It's never a good idea to repeatedly create and delete buffers in your animation loop, as it causes video memory fragmentation. Video memory isn't managed by powerful garbage collectors like in Java or .NET, since it would be in strong contrast to performance. What's freed with "deleteBuffer" might not actually be freed for new use until the complete GL context is deleted.

If you need to use a lot of dynamicly changing buffers, either use the gl.DYNAMIC_DRAW hint which will cause the driver to store the buffer in CPU memory and stream it to the GPU for each individual rendering (at a performance penalty of course) or keep re-using your buffers (over-provisioning its dimension might be advisable).

Many professional 3D engines ever only use one large vertex buffer object for all meshes, using bufferSubData and drawing commands with offsets.

0
votes

By your comment to @mpfefferie, it sounds like your best option is either finding a ready to use (for your needs) objects pool, or making one of your own.

The concept, if not known, is explained in a very clear way on Pool_wiki.

I'd allocate memory for buffers array, if possible. These kind of arrays, that keeps "big" chunks of data are scary. You can never be sure of how much space they really keep for themselves.

Besides, you can re-check that you don't leave any forgotten references to the variables.

If, by any chance, you've got some "spare" time on your pre-load, you can try and pause the rendering for a few moments every once in a while and it might help that poor GC do its job.