Skip to content

Bug: [Fiber] Apps that have data-heavy props or state use hundreds of MBs of extra memory #36176

@leeoniya

Description

@leeoniya

Hello!

I'm a frontend engineer at Grafana, currently investigating excessive/unexpected memory usage.

Grafana is very data-heavy, users run arbitrary queries against databases, and it all ends up in the browser. The existing architecture and plugin/extension ecosystem of Grafana relies on passing this data through a prop to the panel components. We cannot break this contract, so pulling the data out of React props/state is not possible without breaking an enormous amount of existing code that relies on this contract / API.

This was raised back in 2018 in #14380, with tl;dr that this was a known design tradeoff of Fiber. however, the issue was stale-closed with no definitive statement from the core team whether this behavior is something that cannot be mitigated.

I don't know the details of the implementation, but it seems odd that once rendering has settled that the old fiber state cannot be released so it can be effectively GC'd.

React version: 16+ (every version after Fiber replaced the Stack reconciler)

Steps To Reproduce

  1. Put heavy data (such as a db query response) into props, context, state, memo, reducer
  2. When new data replaces old data, the old data remains in memory, causing double the resident memory to be used.

Link to code example:

It appears that the only way to avoid this is to create custom state hooks that internally rely on useRef. and only pass around refs when prop-drilling. i've been playing with these workarounds here: https://github.com/leeoniya/react-memory.

Another approach that works - and is nasty - is to rely on a usePrevious hook to grab and clear the previous data by mutation, like resetting previous data arrays via values.length = 0.

I really want to avoid introducing unusual hooks and non-idiomatic React patterns to our codebase to work around this issue, but i'm not currently seeing a good way to avoid this. Would love some advice, or at least to understand if things will remain this way for the foreseeable future so we can make the right decision.

The current behavior

2x memory

The expected behavior

1x memory

cc @trueadm @acdlite @gaearon

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: UnconfirmedA potential issue that we haven't yet confirmed as a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions