Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Canvas draw and animation creating Memory Leaks #1084

Closed
gitdisrupt opened this issue May 10, 2017 · 6 comments
Closed

Canvas draw and animation creating Memory Leaks #1084

gitdisrupt opened this issue May 10, 2017 · 6 comments
Labels
Milestone

Comments

@gitdisrupt
Copy link

gitdisrupt commented May 10, 2017

Wavesurfer.js version(s):

1.4.0

Browser version(s):

Safari and Chrome

Use behaviour needed to reproduce the issue:

All use cases ...

I was seeing a never ending increase in memory usage when instantiating a wavesurfer instance and playing back an audio file (tried both, as MediaElement and WebAudio) that is NOT released after calling myWave.destroy() to destroy the instance.

At first i suspected the memory leaks had something to do with WebAudio or even the Media element, but then to test this theory, i modified the wavesurfer code and disabled the render of the canvas.

As soon as i disabled the render of the canvas the memory leak was gone.

It seems there are references to the canvas elements, event listeners and animation that are not properly removed on destroy.

@gitdisrupt
Copy link
Author

gitdisrupt commented May 14, 2017

OK EVERYONE!! I can't believe i didn't think to try this earlier ... but i believe i have made a HUGE improvement to performance and memory usage!!

VERY SIMPLY ...
For both the drawBars and drawWave methods, i wrapped their contents with a requestAnimationFrame() call, and this DRAMATICALLY reduced memory usage!!!!

ALSO, at the end of those calls, i cancel the request and NULL the property.

Here is what i did ...

drawBars: function (peaks, channelIndex, start, end) {
        let requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame;
        var scope = this;
        requestAnimationFrame(function() {
            // contents of the drawBars method here
            // all references to this. changed to scope.
        });
        requestAnimationFrame = null;
       scope = null;
}

And then of course i did the same for the drawWave method as well.

I am betting there are other improvements that can be done as it relates to memory leaks, like nulling properties when they are no longer needed, but i feel like this alone makes for a great improvement.

Hey @entonbiba, can this update be applied to the latest version?

With all that said though ... i should point out that when destroying a wave instance, the memory that is used is still NOT released ... VERY important to note ... so this issue should remain open.

I believe though that the memory usage that is never released is likely related to the canvas elements and not necessarily the WebAudio or MediaElement instance.

In the meantime im working to apply the same idea to other methods like fillRect for example

Cheers!!

@entonbiba entonbiba added this to the 1.6 milestone May 16, 2017
@entonbiba
Copy link
Contributor

@gitdisrupt looks fine to me, can you create a pull request for it?

@entonbiba
Copy link
Contributor

entonbiba commented May 16, 2017

@gitdisrupt @mspae @katspaugh I say let's create a util method for requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame; instead and just reference via this.util.requestAF(functionhere(this)); method. This way it will automatically set it to null in the util method.

@katspaugh
Copy link
Owner

This looks cool, @gitdisrupt, thank you very much!

@entonbiba I agree. Actually setting to null looks like some black magic. Does it really do anything? Doesn't the requestAnimationFrame release the callback (along with the scope) after executing it once?

@agamemnus
Copy link
Contributor

Yes, I see a lot of memory leaks on destroy in relatively young libraries, too.

Setting those values to null won't do anything.

PR coming...

katspaugh pushed a commit that referenced this issue Jun 1, 2017
* Wrap drawing in requestAnimationFrame.

Wrap drawing in requestAnimationFrame per #1084.

* Update drawer.canvas.js

* Update drawer.canvas.js

* Update drawer.canvas.js

* Update drawer.canvas.js

* Update drawer.canvas.js
@mspae
Copy link
Contributor

mspae commented Oct 29, 2017

Closing this since the PRs were merged.

@mspae mspae closed this as completed Oct 29, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants