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

Memory leak in React 15.3.0 non-production server side rendering #7406

Closed
franjohn21 opened this issue Aug 2, 2016 · 4 comments · Fixed by #7455
Closed

Memory leak in React 15.3.0 non-production server side rendering #7406

franjohn21 opened this issue Aug 2, 2016 · 4 comments · Fixed by #7455

Comments

@franjohn21
Copy link

franjohn21 commented Aug 2, 2016

A memory leak appears to have been introduced to server side rendering in React 15.3.0 when NODE_ENV != production.

With NODE_ENV=development, the size of the heap grows proportionally to the number of requests received. This was confirmed in both Node v6.3.0 and v0.12.3. Also it was confirmed to work correctly in React 15.2.0.

To reproduce: Start the app configured for server-side rendering with NODE_ENV=development (or just not production). Inspect the V8 heap before and after hitting your server with a number of requests. I used heapdump to take the snapshots and wrk to hit my app with a bunch of requests. Load the snapshots into chrome dev tools profiler. Here is what I see:
screen shot 2016-08-02 at 12 47 34 pm

The culprit appears to be the react children mutation warning. onBeforeComponentMount saves a reference to a given React Element and all of its props in the elements object, but the cleanup steps onComponentHasMounted or onComponentHasUpdated are never called on the server and thus the elements object is ever growing.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
react - 15.3.0
react-dom - 15.3.0
node - 6.3.0 || 0.12.3
express - ^4.0.0

@zpao
Copy link
Member

zpao commented Aug 2, 2016

Awesome detective work. We should fix this.

cc @jimfb @spicyj @gaearon Can we thread the transaction through to the hook to determine if we should store the reference? Or is there something else (I haven't looked closely at the actual hook code if there's precedent).

@gaearon
Copy link
Collaborator

gaearon commented Aug 2, 2016

Hmm, why is this devtool storing elements by itself? They should already be available in ReactComponentTreeDevtool which correctly cleans up on server rendering (we have tests for this). I think this devtool needs to switch to ask ReactComponentTreeDevtool for the element.

@gaearon
Copy link
Collaborator

gaearon commented Aug 2, 2016

Specifically ReactComponentTreeDevtool.getElement(debugId) should provide the same information. Can you test if using that instead of a local dictionary fixes the issue?

@keyz
Copy link
Contributor

keyz commented Aug 2, 2016

The tricky part here is only onBeforeMountComponent and onMountComponent get called while doing SSR. Currently ReactChildrenMutationWarningHook asserts in onComponentHasMounted and onComponentHasUpdated, which are not called.

I think if we want to do this in the SSR code path we might move the assertion to onMountComponent (and get the element from ReactComponentTreeHook as @gaearon mentioned).

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

Successfully merging a pull request may close this issue.

4 participants