Describe the bug
Apps with large numbers of live queries, when unmounting them, trigger deferred garbage collection via setTimeout. setTimeout has a considerable performance impact and looking at the profiler, about half of the entire time spent for a re-render gets spent creating and clearing garbage collection timeouts.
To Reproduce
Steps to reproduce the behavior:
- Create some view with a large list of data, say tweets paginated, 500 per page
- Each Tweet component gets the tweet id passed down as a prop and it gets its own data using it's own useLiveQuery instance to optimise for minimal updates when mutating
- Swap between pages. Each of the 500 tweets will get unmounted and 500 new tweets should be re-mounted.
- Observe performance via any Profiler
- The performance is quite bad, depending on the number of tweets making the page almost unusable
Expected behavior
I expect the performance to be relatively reasonable.
Screenshots
Loads and loads of unmounts:
And most of that time is spent in setTimeout and clearTimeout calls:
Desktop (please complete the following information):
- OS: OSX
- Browser: Chrome
- Version: 145.0.7632.117 (Official Build) (arm64)
Additional context
Can be fixed with a centralised garbage collection queue: the function calls could be pushed to an in-memory queue which is triggered for deferred consumption, doing setTimeout only once during the unmounting process. The individual setTimeout calls will thanks to this happen after the render process.
I tested this in a fork and it gave me 2x performance when using StrictMode where the setTimeouts happen twice per unmount.