Skip to content
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

React retains component references to old renders causing browser memory to increase #18116

Open
tsjohns9 opened this issue Feb 24, 2020 · 13 comments

Comments

@tsjohns9
Copy link

tsjohns9 commented Feb 24, 2020

React version: 16.12.0
Link to deployed demo app - https://tsjohns9.github.io/react-memory-leak/
Link to demo repo - https://github.com/tsjohns9/react-memory-leak

The current behavior

React appears to retain references to old renders of components which prevents the browser from running the garbage collector on unused memory.

The expected behavior

React should release the memory of components from previous renders

Description

I have a web app that imports an OAS 3/Swagger 2.0 json spec file, and renders the file using the swagger-ui component, https://github.com/swagger-api/swagger-ui.

These json files can be very large. If I upload a file that is 500kb and pass it into the swagger-ui component the heap snapshot in chrome will show about 32.6 MB being used to render the app.

At some point during the lifecycle of this component the spec file may be updated by a user. When this happens the swagger-ui component will re-render. Between re-renders I can see from my heap snapshot that about 15 more mb are added to the heap.

Even if this component is completely unmounted, the memory is still retained and cannot be garbage collected.

I would expect that after a re-render the heap size would be about the same, and the old references would be released for garbage collection.

I have come here with this issue and not swagger-ui because based on the heap snapshots the detached DOM elements are being retained by React directly.

The spec file that I have used is about 500kb. Unfortunately it is a proprietary file and I cannot share it here. Instead, I have provided a spec file from swagger-ui. This file is much smaller, but it will serve the purpose of showing how react is retaining references to old component renders. In my situation since the file is so large this becomes much more apparent to the user that there is a problem than with a much smaller json file.

Screen Shot 2020-02-24 at 1 17 42 PM
Screen Shot 2020-02-24 at 1 21 30 PM

Steps To Reproduce

  1. View the app here
  2. Open the console, and take a heap snapshot
  3. Press the Update Spec button in the top left of the app, or the Unmount button
  4. Take another heap snapshot.
  5. You will see that the heap size has increased
  6. Compare the two heap sizes and check to see how many new detached objects there are. Here is a screenshot as an example
    Screen Shot 2020-02-24 at 1 26 19 PM

Link to code example: https://tsjohns9.github.io/react-memory-leak

@tsjohns9 tsjohns9 added the Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug label Feb 24, 2020
@jddxf
Copy link
Contributor

jddxf commented Feb 25, 2020

Does #18066 help?

@tsjohns9
Copy link
Author

That issue seems similar. I downloaded the version that was linked for the fix here as part of #17666, but I am still seeing the memory leak.

@jddxf
Copy link
Contributor

jddxf commented Feb 25, 2020

Did you open it in standalone app view? In my test, there was almost no leak.
image

@tsjohns9
Copy link
Author

The issue I have seems different than the one you have linked too. I am still working to more closely identify what is happening. I will post back here when I know more about what is happening.

@tsjohns9
Copy link
Author

tsjohns9 commented Feb 28, 2020

The running version of react now in the sample app is 0.0.0-241c4467e, which is the same version from the app you linked to. This version has helped with the leak a lot, but I am still seeing a problem with detached dom elements. Go to the deployed demo app here, and take a snapshot. Press the mount button. Take another snapshot. Then unmount and take another snapshot. You will see that the component is no longer in the dom, and yet the memory hardly went down. It looks to me like React is holding onto these elements and is the source of the leak.

This screenshot is from a CRA. I ran a yarn build and had the app running in a private tab to make sure the dev tools weren't holding onto anything extra, and I am still seeing a leak. Please correct me though if I am wrong on that because I can see further down the retainer tree that there is a function called fetchJSON, which I know isn't coming from React.

Screen Shot 2020-02-28 at 11 44 42 AM

@tsjohns9
Copy link
Author

tsjohns9 commented Feb 28, 2020

I have deployed the demo here for your convenience

@shenzekun
Copy link

I also encountered this problem

@gaearon gaearon added Type: Needs Investigation and removed Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug labels Apr 19, 2020
@jianfenkezhan
Copy link

jianfenkezhan commented Aug 14, 2020

react@16.13.1
react-dom@16.13.1
image
image

I am still seeing the memory leak.

@Regaddi
Copy link

Regaddi commented Jul 23, 2021

Here is a minimal reproduction demonstrating the issue on a HTMLVideoElement:

https://codesandbox.io/s/upbeat-butterfly-vchn2?file=/src/App.js

Using react and react-dom 17.0.2.

I was testing in Chrome 92.0.4515.107 on macOS Big Sur 11.4 (20F71).

@vespasianvs
Copy link

Just wondered if there had been any progress on this issue? Also experiencing it as an issue on our app which eventually causes the browser to run out of memory. Is there even a temporary workaround?

@jddxf
Copy link
Contributor

jddxf commented Nov 9, 2021

@Regaddi I can see leaks without React too:
https://codesandbox.io/s/ixz0g
You could fix the problem by clearing srcObject when removing the video element.

It's actually an issue of chromium:
https://bugs.chromium.org/p/chromium/issues/detail?id=969049#c48

@gaearon
Copy link
Collaborator

gaearon commented Mar 30, 2022

React 18 clears up memory more aggressively. Can somebody please check if this is still as severe?

@miklosme
Copy link

@gaearon We had a memory leak bug report. Although I couldn't reproduce a crash, I saw a lot of uncollected FiberNodes in the memory profiler. After a 17.0.2 -> 18.2.0 upgrade it looks significantly cleaner now:

17.0.2
Screen Shot 2022-09-13 at 6 07 40 PM

18.2.0
Screen Shot 2022-09-13 at 6 21 27 PM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants