-
Notifications
You must be signed in to change notification settings - Fork 1.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
Memory leak when using atomFamily/selectorFamily #366
Comments
Could this be related? I am getting this warning and cannot seem to figure out a way to get rid of it.
|
I have the same issue like @trivigy in a unit test with react testing library. Can't get rid of the warning. |
I don't think that warning should be related. |
@mondaychen Still experience the same issue but I just squint my eye to not see so it wouldn't bother me. 😆 |
I've started to see errors like that more often with version 0.2.0. Though I don't use async selectors. |
@trivigy @ltwlf @chybisov @ianstormtaylor I don't think the warning is related to the memory issue related to family utils. Let's start a new thread to discuss that. It will be really helpful if anyone can provide a way to reproduce the issue you are describing and create a new issue with that. |
@mondaychen I think you're right. I added a comment here: #951 (comment) |
Just FYI we are working on the memory issue with use of family utils, and should have something to announce about it in the near future. |
Any update on this? |
Hi All, Can we use 'most-recent' instead of 'keep-all' here in atom Family? |
That would mean only the most recent atom used in the family would be retained. |
Hi @mondaychen . Does the recent release (0.7.4) address any of this, or are those leaks elsewhere? |
My current solution is to create all atom families in a React Context and const { myAtomFamily } = useAppAtoms()
const value = useRecoilValue(myAtomFamily(key)) This way the created atoms are scoped to the lifetime of the Context.Provider and I don't need to fiddle the the cache strategy. This approach does releases the atom objects themselves when the app unmounts Is there any doc outlining how memory management works in recoil? Is this strategy flawed? |
That solution only controls the lifetime of the atom objects or the atom family closure which contains the dictionary of cached atom objects. While removing that would remove some minimal memory, the actual registered atom accounting structures, selectors, and selector caches would still be held in the runtime. If you would like to explore or finish memory management in Recoil use the |
@drarmstr can you be more specific on how we can achieve it? |
You can add Would be interesting if someone wanted to do a PR for mapping GK flags here with the new |
Summary: In #366 (comment), it was suggested that we could possibly use `RecoilEnv` to dynamically enable GKs: > Would be interesting if someone wanted to do a PR for mapping GK flags here with the new `RecoilEnv.js` mechanism to more easily dynamically adjust features without rebuilding.. Well, I wanted to try out the transition support in the same way OP of that issue wanted memory management, so I decided to give the implementation a try: this change adds a new property to `RecoilEnv`, `RECOIL_GKS_ENABLED_UNSTABLE`, which can be used to enable certain GKs at runtime. When the property is updated, its changes are proxied to the underlying GK implementation. Pull Request resolved: #2078 Test Plan: CI, unit tests Reviewed By: drarmstr Differential Revision: D40688490 Pulled By: wd-fb fbshipit-source-id: 8a748d453e22782c6122a8d5047155019c5d3a1c
The |
The linked PR (#2143) does not fix this issue
If the |
Maybe guys you could try something I did #1864 (comment) |
Summary: In facebookexperimental/Recoil#366 (comment), it was suggested that we could possibly use `RecoilEnv` to dynamically enable GKs: > Would be interesting if someone wanted to do a PR for mapping GK flags here with the new `RecoilEnv.js` mechanism to more easily dynamically adjust features without rebuilding.. Well, I wanted to try out the transition support in the same way OP of that issue wanted memory management, so I decided to give the implementation a try: this change adds a new property to `RecoilEnv`, `RECOIL_GKS_ENABLED_UNSTABLE`, which can be used to enable certain GKs at runtime. When the property is updated, its changes are proxied to the underlying GK implementation. Pull Request resolved: facebookexperimental/Recoil#2078 Test Plan: CI, unit tests Reviewed By: drarmstr Differential Revision: D40688490 Pulled By: wd-fb fbshipit-source-id: 8a748d453e22782c6122a8d5047155019c5d3a1c
Building on @Tomas2D finding, this is my solution for now until import { useCallback, useEffect } from 'react'
import { releaseNode, useGetRecoilValueInfo_UNSTABLE, useRecoilCallback, useStoreRef } from 'recoil'
type RECOIL_GARBAGE_COLLECTOR_UNSTABLE_Props = {
shouldCheckForGarbageCollection: (key: string) => boolean
interval: number
}
/**
* TODO: remove after `retainedBy` support is implemented on recoil
*/
export const RECOIL_GARBAGE_COLLECTOR_UNSTABLE = (props: RECOIL_GARBAGE_COLLECTOR_UNSTABLE_Props) => {
const storeRef = useStoreRef()
const getRecoilValueInfo = useGetRecoilValueInfo_UNSTABLE()
const releaseUnusedNodes = useRecoilCallback(
({ snapshot }) =>
() => {
if (storeRef.current === null) {
return
}
const releaseSnapshot = snapshot.retain()
const state = storeRef.current.getState()
for (const node of snapshot.getNodes_UNSTABLE()) {
if (!state.knownAtoms.has(node.key) && !state.knownSelectors.has(node.key)) {
continue
}
if (props.shouldCheckForGarbageCollection(node.key)) {
const firstNodeSubscriber = snapshot.getInfo_UNSTABLE(node).subscribers.nodes[Symbol.iterator]().next()
// Can't use `snapshot.getInfo_UNSTABLE` here
// https://github.com/facebookexperimental/Recoil/issues/1684
const firstComponentSubscriber = getRecoilValueInfo(node).subscribers.components[Symbol.iterator]().next()
const hasNoSubscriber =
firstNodeSubscriber.done &&
firstNodeSubscriber.value === undefined &&
firstComponentSubscriber.done &&
firstComponentSubscriber.value === undefined
if (hasNoSubscriber) {
releaseNode(storeRef.current, state.currentTree, node.key)
}
}
}
releaseSnapshot()
},
[getRecoilValueInfo, props, storeRef]
)
useEffect(() => {
const interval = setInterval(releaseUnusedNodes, props.interval)
return () => clearInterval(interval)
}, [props.interval, releaseUnusedNodes])
return null
} Which can be used like so <RECOIL_GARBAGE_COLLECTOR_UNSTABLE
interval={5_000}
shouldCheckForGarbageCollection={useCallback(
node => node.startsWith('MyState') || node.startsWith('SomeOtherState'),
[]
)}
/> This will basically check for & release all unused nodes every |
Summary: In facebookexperimental/Recoil#366 (comment), it was suggested that we could possibly use `RecoilEnv` to dynamically enable GKs: > Would be interesting if someone wanted to do a PR for mapping GK flags here with the new `RecoilEnv.js` mechanism to more easily dynamically adjust features without rebuilding.. Well, I wanted to try out the transition support in the same way OP of that issue wanted memory management, so I decided to give the implementation a try: this change adds a new property to `RecoilEnv`, `RECOIL_GKS_ENABLED_UNSTABLE`, which can be used to enable certain GKs at runtime. When the property is updated, its changes are proxied to the underlying GK implementation. Pull Request resolved: facebookexperimental/Recoil#2078 Test Plan: CI, unit tests Reviewed By: drarmstr Differential Revision: D40688490 Pulled By: wd-fb fbshipit-source-id: 8a748d453e22782c6122a8d5047155019c5d3a1c
Hello there,
The resources created by
atomFamily
andselectorFamily
are not being properly freed when the specifickey
changes or if the component using the relatedRecoilState<T>
unmounts.Since I believe that memory management isn't properly implemented yet, both utils should be marked as
_UNSAFE
.https://codesandbox.io/s/cranky-booth-penix?file=/src/App.js
The text was updated successfully, but these errors were encountered: