Skip to content

Potential performance issues with using forwardRef #13456

Closed
@markerikson

Description

@markerikson

Do you want to request a feature or report a bug?

Bug (assuming that a potential drop in perf counts as a "bug")

What is the current behavior?

I've been setting up a rudimentary perf benchmark harness for React-Redux over in reduxjs/react-redux#983 , so that we can compare performance between builds of React-Redux as we work on version 6. The harness runs one or more benchmark apps in headless Puppeteer, running them once to capture FPS values and a second time to capture Chrome trace reports automatically.

Currently, there's only one benchmark app: a "stock ticker"-type stress test that measures FPS by using the fps-emitter package (which relies on requestAnimationFrame). It's rough, but it does show meaningful differences in FPS values as we swap between different React-Redux builds and change the number of connected components in the benchmark.

We have two WIP candidate PRs for React-Redux v6: reduxjs/react-redux#995 and reduxjs/react-redux#1000 . Initial testing showed that PR 995 was almost as fast as our existing 5.0.7 version, while PR 995 was slower in some runs. However, my initial push of the 995 branch did not include use of React.forwardRef, while the 1000 branch already had that added.

I spent Saturday adding forwardRef and a couple other pieces of functionality to the 995 branch, then re-ran the benchmarks. Per ourcomments in the 983 issue, we saw that the 995 branch had suddenly gotten slower, and that removing forwardRef from the 1000 branch sped things up by a few FPS.

This is admittedly a very artificial stress test scenario, but it's also likely that React-Redux apps can have hundreds or thousands of connected components at once, so the potential slowdown seems concerning.

If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem. Your bug will get fixed much faster if we can run your code and it doesn't have dependencies other than React. Paste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or CodeSandbox (https://codesandbox.io/s/new) example below:

The current perf benchmark repo is at https://github.com/markerikson/benchmark-react-redux-perf . It uses UMD builds of React-Redux so that it can easily switch which build is being used. Several UMD builds are already committed there in the root of the repo. 6.0-mark is the 995 branch, and 6.0-greg is the 1000 branch. They can be reproduced by building their respective branches from the PRs. I've been hand-copying the UMD build artifact from my React-Redux clone over to this benchmark folder and renaming it to whatever seems appropriate.

Clone the repo, yarn to install, yarn perf to build and run the benchmark. Number of connected components can be modified in src/constants.js (requires rebuilding). The harness determines which UMD build versions to run based on an array in perfBenchmark.js, around line 11 (const VERSIONS = ["5.0.7", "6.0-mark"]).

What is the expected behavior?

That there would be minimal to no impact in perf when forwardRef is used to wrap a component such as a HOC, and that HOC is used widely in an application.

Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?

I've been testing this with Puppeteer 1.6.2, on Windows 10. It looks like the locally installed version of Chromium is 69.0.3494.0 .

Current version of React is 16.4.2, UMD build (as React-Redux UMD expects that both React and Redux are also global variables). I have not tested against a prior version of React, as we are specifically targeting 16.4+ with this next version of React-Redux.

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