Snap.svg: Memory leaks
Hi, first off thanks for the hard work on snap.
I found that my animations were leaking memory (and found that the problem could be reproduced by debugging the demos > snap-mascot page) and did some digging. Turned out that the issue was with the following handlers:
eve.once("mina.finish." + anim.id, function () {
delete el.anims[anim.id];
callback && callback.call(el);
});
eve.once("mina.stop." + anim.id, function () {
delete el.anims[anim.id];
});
When the mina.stop event triggers the handler for the mina.finish event is not deleted and vice versa. The handlers remain in memory until the application is terminated since they are referenced by eve’s events property.
I fixed the issue by removing mina.stop altogether and triggering mina.finish in stopit. There is still a less major memory leak issue involving the handlers but I haven’t fixed it yet.
Hope this helps someone, cheers.
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Comments: 26 (8 by maintainers)
Commits related to this issue
- Fixes #369. — committed to adobe-webplatform/Snap.svg by deleted user 9 years ago
- Bumped eve’s version Fixes #369. — committed to adobe-webplatform/Snap.svg by DmitryBaranovskiy 7 years ago
Ok - This is just a simple fix, re-factoring for better overall performance got messy. The Eve bind methods are already quite heavy so this doesn’t add much, most of the work is still done in the GC.
For convenience I’ve built this on my fork along with two other small fixes I’ve done, but please don’t rely on it being here permanently: https://github.com/ThomasBrierley/Snap.svg/releases/tag/memory-leak-fix
Here’s a basic test running 1000 animations per second. It would be great if anyone could let us know this works for your test case too: http://jsfiddle.net/afv3gdvp/
Oh yeah and Snap on the name @ibrierley 😛 (sorry)
Hi @JeremyTCD I’m not sure VM optimising compilers are part of this problem, compiled code aught to be pruned as part of GC. Either way, expired event objects are still accumulating in the JavaScript heap, and it’s Snap’s responsibility to free references to these for the GC.
I found another accumulation of references within the event library “Eve”. I think these might be the last of them: The event constructor / destructor are asymmetrical, the constructor walks the event tree creating any absent i-nodes in the event path before creating it’s target event; the destructor removes it’s target event from the tree but does not remove empty nodes in the event path above. For most events this results in a trail of redundant parent nodes.
Fixing the destructor to remove empty parents was relatively easy; ensuring the process is reasonably performant was a bit more tricky. Periodic purges cause larger GC spikes, so it needs to be integral to the destructor, which means event path search and removal should be optimised - which requires a bit of careful re-factoring. In my tests the GC reliably reclaims the heap (dispatching thousands of Snap animations per second), with reasonable performance (without pooling GC gota happen).
I actually did this three months ago, but Snap and Eve have become stagnant so i had little motivation to tidy it into a PR. I’ll do a PR for Eve if there is still interest … i guess it’s worth it if people have the option to merge it into their own fork 😃