Memory Leak on React Native iOS
See original GitHub issueWe notice a memory leak with the simplest usage of Recoil when running React Native with Expo on iOS.
The reproducing app is this:
import { registerRootComponent } from "expo";
import React, { useEffect, useRef } from "react";
import { Text } from "react-native";
import { atom, RecoilRoot, useRecoilState } from "recoil";
registerRootComponent(App);
function App() {
return (
<RecoilRoot>
<MyComponent />
</RecoilRoot>
);
}
function MyComponent() {
const [state, setState] = useRecoilState(myAtom);
const updateState = () => setState(constructBigFatObject());
useEffect(() => {
const handle = setTimeout(updateState, 1);
return () => clearTimeout(handle);
}, [state]);
const renderCount = useRef(0);
return <Text>{renderCount.current++}</Text>;
}
const myAtom = atom({
key: "myAtom",
default: constructBigFatObject()
});
function constructBigFatObject() {
const obj = {};
for (let i = 0; i < 10000; i++) {
obj[i.toString()] = i;
}
return obj;
}
Basically we repeatedly create big objects and set them as atom
state.
On Android, everything works fine, memory is constant, but on iOS, memory usage of the app keeps increasing forever (until OOM).
If we replace useRecoilState
with a normal useState
, this effect vanishes, so it is not a problem of the Garbage Collector not working at all, but for some reason, it is not working for Recoil States.
This is with both 0.2.0
and 0.3.1
.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:1
- Comments:9 (2 by maintainers)
Top Results From Across the Web
Solving Memory Leaks with React Native - Enquero
In essence, memory leaks can be defined as memory that is not required by an application anymore that for some reason is not...
Read more >How to Improve React Native App Performance in 2023 Tips
Memory Leaks in React Native · Run React Native app normally (react-native run-android) · Run Android Studio · On the menu, click Tools...
Read more >Hunting JS memory leaks in React Native apps
One of the most common reasons of performance issues are memory leaks. In this article, we gathered the typical approaches to debug and...
Read more >Finding memory leaks react-native app (iOS) - Medium
Problem: Our react-native app was working well on all devices and except iPhone 6 it was resulting in a crash. After high level...
Read more >How to find out memory leaks in react native app?
If you go to profiler, then you will see a graph of your memory, then you can see if the momory increases every...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Hey folks 👋 First, thank you for this amazing library! 👏
I want to share my findings with you. I added
atomFamily
andselectorFamily
to @bearbytes code because I wanted to have some dependencies. To make it a little bit more complicated.Here is the whole repo: https://github.com/xotahal/recoil-leak (just
yarn
,yarn start
&yarn ios
to run the app) TheApp.tsx
is here: https://github.com/xotahal/recoil-leak/blob/master/App.tsx And here’s the simple recoil state I was using:Then my test case was increment
versionState
and for each version create a new selector inmySelector
family.I ran the app in a production build. Then I created 30 new selectors and took a memory snapshot. I found that every time when I created a new selector family recoil created a new state and kept the previous state. These are all version of states I had in memory snapshot.
Questions
@drarmstr I can verify that this occurs in a production build. I’ve been testing exclusively in production builds. Production builds disable the debug atom state history, but selectors are currently retaining every input and every output for all time.
If you remove the selector from the example, and run in production mode, the memory leaks are substantially less. It’s a selector problem.