Skip to content
This repository was archived by the owner on Jun 26, 2020. It is now read-only.
This repository was archived by the owner on Jun 26, 2020. It is now read-only.

Large amount of data in component props causes devtools to peg CPU #1200

@vaughnkoch

Description

@vaughnkoch

Problem:
If a React component has a large amount of data passed in props, even by reference, the CPU gets pegged after the component renders.

Repro

  • Create an array or object structure with a large amount of data, for example 10-20MB.
  • Pass the array variable as the props of a component.
  • Render the component.

This produces the following error:

Uncaught Error: Message length exceeded maximum allowed length.
    at PortImpl.postMessage (VM27 extensions::messaging:121)
    at Port.publicClassPrototype.(anonymous function) [as postMessage] (extensions::utils:138:26)
    at handleMessageFromPage (contentScript.js:24)

The bottom function is this:

    function handleMessageFromPage(evt) {
        evt.source === window && evt.data && "react-devtools-bridge" === evt.data.source && port.postMessage(evt.data.payload);
    }

Here's the current implementation of postMessage which is currently stringifying all the props for the component. Even if they're passed by reference, JSON.stringify still has to process all the data.

  PortImpl.prototype.postMessage = function(msg) {
    if (!$Object.hasOwnProperty(ports, this.portId_))
      throw new Error(kPortClosedError);

    // JSON.stringify doesn't support a root object which is undefined.
    if (msg === undefined)
      msg = null;
    msg = $JSON.stringify(msg);
    if (msg === undefined) {
      // JSON.stringify can fail with unserializable objects. Log an error and
      // drop the message.
      //
      // TODO(kalman/mpcomplete): it would be better to do the same validation
      // here that we do for runtime.sendMessage (and variants), i.e. throw an
      // schema validation Error, but just maintain the old behavior until
      // there's a good reason not to (http://crbug.com/263077).
      console.error('Illegal argument to Port.postMessage');
      return;
    }
    var error = messagingNatives.PostMessage(this.portId_, msg);
    if (error)
      throw new Error(error);
  };

Notes/Thoughts

  • A large amount of data in props passed by ref can be a legitimate use case, for example using Vega for dataviz. Usually this isn't a problem since they're passed by ref.
  • Are there any other ways to serialize arbitrary JS objects instead of JSON.stringify, for example using Apache Arrow?
  • If the props are only used for display to the user in the inspect or profiler ui, would it make sense to just send the first 10-20 elements in an array and tell the user that the data was clipped? Not sure how you'd handle this with arbitrarily large objects though.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions