-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
[Bug] Local helpers and modifiers cause memory leaks #20535
Comments
I haven't looked in to this too deeply yet, but here is the manager for plain functions:
I wonder if the manager infra is holding on to the function reference Upon further snooping, I found a helper definition cache
idk if you want to dig in to glimmer, but resolving any sort of memory leak would be a huge help <3 💪 as an aside, how do find out what is still holding on to a reference? |
My stab at a fix: glimmerjs/glimmer-vm#1440 |
I think this can now be closed since glimmerjs/glimmer-vm#1440 was merged and the VM update with the fix made it into Ember v5.7+. |
🐞 Describe the Bug
Anytime a component that has a local modifier or helper is rendered, that modifier/helper object/function will be retained in memory even after the component is un-rendered (it is released when the app exits). The fact that it is retained after the component is un-rendered is why I'm calling it a memory leak.
This has two implications that, especially when considered together, can cause quite a lot of memory to leak:
readonly myHelper = function myHelper() { return 'hello'; }
, then a copy of themyHelper
function will leak for each component instance that is rendered/un-renderedthis
), then the component instance itself will leak🔬 Minimal Reproduction
This repository contains a minimal reproduction of the issue, both via an integration test, and steps for a manual repro in the dummy app.
😕 Actual Behavior
After rendering and un-rendering a component that invokes a local helper, that local helper function leaks.
🤔 Expected Behavior
It should be released when the component is un-rendered.
🌍 Environment
➕ Additional Context
I dug in some and believe I have a diagnosis of the problem. Here is the culprit retainer chain:
The
CompileTimeCompilationContextImpl
is effectively a singleton, as isConstantsImpl
. When the local helper is first invoked,ConstantsImpl
'shelper()
method is invoked, which calls intovalue()
, which puts an object containing the helper arrow function in athis.values
andthis.indexMap
:They are not removed until the app exits.
This is some guesswork, but it appears that these helpers are being stored in the same place as global helpers, so the pattern is to keep them cached forever, but really they should be stored in a place/manner such that their lifetime is bound to the lifetime of the component, and/or they should stored via weak references.
The text was updated successfully, but these errors were encountered: