Open ascott18 opened 5 years ago
There seems to be a PR for this (https://github.com/vuejs/vue/pull/8157, which appears to have languished), but I wasn't able to find a related issue.
It's probably going to be a part of Vue 3.x as stated in https://github.com/vuejs/vuex/issues/1383#issuecomment-429617484
Version
2.6.10
Reproduction link
https://jsfiddle.net/b9at5703/
Steps to reproduce
Click the button to toggle the render of the children on and off. Adjust the number of children rendered in the template.
Increasing the number of children by 10x (from 10,000 to 100,000) increases the render time by 10x, but increases the teardown time by 33x (from ~0.6s to 20s in my testing). I realize that 100,000 components is a pretty unrealistic use case, but please continue reading below.
What is expected?
Teardown time for components should scale linearly with the number of components, not exponentially.
What is actually happening?
In the repro link, every component has its own subscription against
$root.theme
. This is fine on its own, but subs are stored in an array, requiring anO(n)
search to find the sub in order to remove it from the array.This particular example is actually an extremely optimistic case - the subs are added to the array in order that the components are rendered, and then the components are destroyed in the order they are rendered. This means that the sub being removed is always found at the very beginning of the
subs
array, so theindexOf
call inremove()
(https://github.com/vuejs/vue/blob/dev/src/core/observer/dep.js#L28) can return almost immediately.This is why I had to go to really high numbers of components (10k-100k) to make the problem very evident, but in my real-world application, I'm seeing this issue at 1,000 components or less (in a large data table component).
Now, imagine a scenario where a complex application has a large component tree with subs to some root
theme
prop all over the place. In fact, this is exactly what happens in a Vuetify app. As components are destroyed, their sub to this root value could be anywhere in thesubs
array.Ran into this while using Vuetify, which has a subscription to
$vuetify.isDark
(saw 1700 subs), or to$vuetify.theme.dark
(saw 1000 subs) in a large number of its components. I also saw 300 subs to$route
, which could easily balloon much bigger if I added some router-links to some of the fields in my table cells.