ractive: Memory leak when using components
Description:
Took me hours to pin this issue down in my SPA, but finally managed to reproduce it in a few lines of code 😪 Looks like Ractive 0.8 keeps pointing to unused DOM elements (and possibly something else? whole components?) after their component is teardown.
This may result in big memory leaks, depending on the size of your components. The more the elements, the bigger the memory being leaked.
I started noticing it on components where 4k-20k elements were being removed. Narrowed it down to a minimal example.
Let me know if I can be of any help.
Versions affected:
0.8.11 notably, 0.7.3 is NOT affected
Platforms affected:
Any browser
Reproduction:
http://jsfiddle.net/trc4m077/4/
- fire up the inspector (ex. Chrome)
- activate inspector’s Memory tab
- click the button “TOGGLE ME”, from my fiddle
- use the Inspector to take a Heap Snapshot
- filter objects by using the Class filter: “detached DOM Tree”
you should see 3 groups of Detached DOM Tree:
- ignore the first two, which are related to jsFiddle
- the third one should include 4 entries, all of which appear to be linked to Ractive
Those 4 entries will be a lot more, if you’re building anything more complex than my example.
See also the attached screenshots from my inspector.
All screenshots have been taken after ApplicationHeader had been toggled off.



Code:
Interestingly, if you remove the {{name}}, no memory will be leaked.
From my tests, memory leaks even if ApplicationHeader is marked as isolated: true, and name gets passed via attribute.
const ApplicationHeader = Ractive.extend({
template: `
<nav class="header">
<section>
My name is {{name}}
</section>
</nav>
`,
});
const Application = Ractive.extend({
template: `
<button on-click="toggle('hideComponent')">TOGGLE ME</button>
{{#if !hideComponent}}
<ApplicationHeader/>
{{/if}}
`,
components: {
ApplicationHeader,
},
data: () => ({
name: 'Laser',
}),
});
window.r = new Application({ el: '#application' });
About this issue
- Original URL
- State: closed
- Created 7 years ago
- Reactions: 1
- Comments: 39 (37 by maintainers)
The great news is that the number of detached trees in my app went down dramatically 😃 Tested on a page that used to have 24k of them, and you can definitely feel the difference!
I’ll still investigate the very few other leaks I’m experiencing, as they might be a big deal for other people.
Things are beginning to work quite nicely 😎 🎉
Isolated the EventDirective leak (biggest offender now): http://jsfiddle.net/7w5sq8ad/3/
Notably, no leak when using the deprecated bindings:
Meteor 0.6… those were the days. 😄
Awesome work folks. We @mixmaxhq used to use Meteor i.e. Blaze for our frontend, then switched to Backbone due to performance problems, but are now considering Ractive to simplify some complex UIs, and it’s terrific to see that there’s such a great community actively improving it.
Ah! There was an old deploy script on the 0.8 branch. I’ve updated it, and build-11 is now published.
Thanks for doing the tracking! I’ve pushed out 0.8.12 🎉
Confirmed as fixed. Tested build-11 it quite a bit today, and found nothing new.
As far as I can tell, I think we’re done here 🎉 🎉 🎉 😄 I’ll keep an eye on memory consumption from now on, and open new issues if necessary.
Again, thank you so much @evs-chris for the massive help! 0.8.12 is going to be a pretty awesome minor release! 😎
I took a swing at a potential issue involving multiple rebinds (splices) in one turn of the runloop that may resolve that first issue. Since it’s an issue with unresolveds, it shouldn’t affect edge. The 0.8 build with the change is 0.8.12-build-10.
@mefjuu a great post on the matter is: https://developers.google.com/web/tools/chrome-devtools/memory-problems/
Specifically the section: Discover detached DOM tree memory leaks with Heap Snapshots
Offtopic: could you explain shortly how to read such snapshots to find memory leaks?