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

[DevTools Bug]: Consistent memory leak when refreshing on React + non-React websites. #28323

Closed
braeden opened this issue Feb 14, 2024 · 16 comments
Assignees
Labels
Component: Developer Tools Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug

Comments

@braeden
Copy link

braeden commented Feb 14, 2024

Website or app

https://google.com

Repro steps

With Chrome version 121.0.6167.184 (Official Build) (arm64)

React dev tools: 5.0 - Created from revision 993c4d003 on 12/5/2023.

Repeatedly refreshing https://google.com continually leaks memory.

With React Dev Tools

Some memory is retained temporarily between refreshes, but notably forcing GC (the trashcan button), never shrinks + each subsequent refresh monotonically increases memory overhead.

With.React.dev.tools.mov

Without React Dev Tools

Forcing GC without react dev tools drops the memory footprint from ~100MB to ~10MB instantly.

without.react.dev.tools.mov

Other debugging:

Went down a massive rabbithole of Chrome version bisection (memory between refreshed started to be retained a bit longer with this V8 GC change), but it always GC'd correctly when being forced: https://chromium.googlesource.com/v8/v8/+/7477604415624e2f60000194f766e2f404e02fed.

Other notes:

  • This was in incognito mode without any other extensions enabled
  • Happy to provide heap snapshots (it appears that retained memory is mostly closure + compiled code) + hopefully this should be simple to repro.

How often does this bug happen?

Every time

DevTools package (automated)

No response

DevTools version (automated)

No response

Error message (automated)

No response

Error call stack (automated)

No response

Error component stack (automated)

No response

GitHub query string (automated)

No response

@braeden braeden added Component: Developer Tools Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug labels Feb 14, 2024
@pwbriggs
Copy link

This was in incognito mode without any other extensions enabled

Just wondering, how'd you install React DevTools in incognito?

@braeden
Copy link
Author

braeden commented Feb 14, 2024

This was in incognito mode without any other extensions enabled

Just wondering, how'd you install React DevTools in incognito?

There's an Allow in Incognito switch in the Details of any Chrome extension.

image

@pwbriggs
Copy link

I see, thanks.

@hoxyq hoxyq self-assigned this Feb 14, 2024
@hoxyq
Copy link
Contributor

hoxyq commented Feb 14, 2024

Thanks for reporting this and recording a demo, I will try to triage this early next week, hopefully shipping a fix soon.
If someone is already triaging this, feel free to open a PR and mentioning this issue.

@mkdynamic
Copy link

I see similar behavior when the React Dev Tools is enabled, across all sites. Looking at the heap snapshots, you can see the previous window objects retained and accumulate on every reload. Maybe the Dev Tools is hanging on to a reference for every window object?

@hoxyq
Copy link
Contributor

hoxyq commented Feb 21, 2024

Attempted to triage this, noticed that the required condition for this to happen is chrome.devtools.network.onNavigated listeners here:

chrome.devtools.network.onNavigated.addListener(syncSavedPreferences);

chrome.devtools.network.onNavigated.addListener(debouncedOnNavigatedListener);

Removing both of them fixes the issue.

Having at least one of them still reproduces the memory leak, which is surprising, given the fact that the first one (syncSavedPreferences) is only using chrome.devtools.inspectedWindow.eval:

// The renderer interface can't read saved component filters directly,
// because they are stored in localStorage within the context of the extension.
// Instead it relies on the extension to pass filters through.
function syncSavedPreferences() {
chrome.devtools.inspectedWindow.eval(
`window.__REACT_DEVTOOLS_APPEND_COMPONENT_STACK__ = ${JSON.stringify(
getAppendComponentStack(),
)};
window.__REACT_DEVTOOLS_BREAK_ON_CONSOLE_ERRORS__ = ${JSON.stringify(
getBreakOnConsoleErrors(),
)};
window.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = ${JSON.stringify(
getSavedComponentFilters(),
)};
window.__REACT_DEVTOOLS_SHOW_INLINE_WARNINGS_AND_ERRORS__ = ${JSON.stringify(
getShowInlineWarningsAndErrors(),
)};
window.__REACT_DEVTOOLS_HIDE_CONSOLE_LOGS_IN_STRICT_MODE__ = ${JSON.stringify(
getHideConsoleLogsInStrictMode(),
)};
window.__REACT_DEVTOOLS_BROWSER_THEME__ = ${JSON.stringify(
getBrowserTheme(),
)};`,
);
}

Few ideas:

  1. I don't have the time right now, but maybe its worth trying to create a small reproducible example of an extension, which uses both chrome.devtools.network.onNavigated and chrome.devtools.inspectedWindow.eval, which has the same memory leak issues?
  2. Does this memory leak happen in Firefox as well?

@chrishoage
Copy link

Does this memory leak happen in Firefox as well?

I believe it does, yes. Today I noticed excessive memory usage in Firefox. I opened about:processes and saw "Extensions" using 5GB of memory.

One by one I turned off my extensions (not many, just 4) and watched the report on the memory usage for extensions.

Once I turned off "React Developer Tools" the memory usage for the "Extensions" line in about:processes went from over 5GB down to 600MB.

While I admit this anecdote isn't conclusive proof I think it serves as evidence that it could happen in firefox as well.

@jryans
Copy link

jryans commented Feb 22, 2024

Similar to @chrishoage, I have also observed this memory leak in Firefox in the form of high memory usage (though I saw it in happening in a React-using content process) which seemed to go away after disabling this extension.

@hoxyq
Copy link
Contributor

hoxyq commented Feb 22, 2024

I am currently exploring an option to switch from chrome.devtools.inspectedWindow.eval to chrome.scripting.executeScript.

The main problem for us with this approach is the requirement for executing scripts in MAIN world, which Firefox doesn't support yet.

@WizardAlice
Copy link

It took me a whole Friday afternoon to finally find the issue came from this plugin.

@hoxyq
Copy link
Contributor

hoxyq commented Feb 29, 2024

My Chrome got updated, and I can't reproduce this on Chrome v122.0.6261.69, can someone confirm this as well?

@braeden
Copy link
Author

braeden commented Mar 1, 2024

Also cannot reproduce anymore 😬 (same chrome version as @hoxyq ).

I'm slightly concerned that this might reappear unless we can pinpoint the Chromium commit that might have changed the behavior here...

@liy9426
Copy link

liy9426 commented Mar 8, 2024

chrome v122.0.6261.112 still having this problem.....even if the webpage is not using React at all
subscribed to window 'message' event but consistently receving message with source 'react-devtools-content-sceipt'

@erikasby
Copy link

Chrome Version 122.0.6261.129 (Official Build) (64-bit)
Can't reproduce. Refreshes accumulate MB infinitely, but waiting for ~5 seconds or pressing "Collect garbage" flushes everything instantly down to ~10 MB.

Firefox Version 123.0.1 (64-bit)
Measured private window in about:processes with and without React Dev Tools - memory behavior seems to be the same. Was able to instantly free up memory in about:memory with Free memory - GC on both occasions. From ~500 MB to ~210 MB instantly.

I guess not a Chromium or Firefox issue then if both browsers suddenly behave properly, or it can be?

@hoxyq
Copy link
Contributor

hoxyq commented Mar 25, 2024

Since we can't reproduce this, I am going to close this. Would be nice if someone can grep the changes from between Chrome 121 and Chrome 122 to identify the affecting commit, but this would require some time.

@torchesburn
Copy link

Since we can't reproduce this, I am going to close this. Would be nice if someone can grep the changes from between Chrome 121 and Chrome 122 to identify the affecting commit, but this would require some time.

you literally just refresh the tab and see the memory grow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Developer Tools Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug
Projects
None yet
Development

No branches or pull requests

10 participants