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

Possible regression in dev mode in v16.3 #12502

Closed
gregberge opened this issue Mar 31, 2018 · 18 comments · Fixed by #12510
Closed

Possible regression in dev mode in v16.3 #12502

gregberge opened this issue Mar 31, 2018 · 18 comments · Fixed by #12510

Comments

@gregberge
Copy link

This example presents a huge performance drop between React 16.2 and React 16.3.

In investigated it and noticed several things:

  • Perfomance drop is only visible using development bundle
  • This is not related to styled-components (a simple div presents the same problem)
  • I tried to investigate in performance tab of Chrome dev tools and I noticed that I get React measures even without "?react_perf"
  • React Tree Reconciliation seems very long, do not know why

It is not a big problem for me, but it looks weird, so I decided to share it on Twitter, then @gaearon invited me to submit an issue about it.

@gaearon
Copy link
Collaborator

gaearon commented Mar 31, 2018

Can you turn this into a smaller self-contained example without third party libs?

@gregberge
Copy link
Author

I will try to do it but right now I don’t have time, I think doing a setState every 16ms on 20 components in parallel should be sufficient to make it slow.

@sebmarkbage
Copy link
Collaborator

Note that if you’re using the StrictMode component, this is expected since it double renders. If you’re not, then it is not expected and probably a bug.

@alshakero
Copy link

alshakero commented Mar 31, 2018

Here is a fairly simple comparison. Exactly the same code with different react versions:

@mlazowik
Copy link

mlazowik commented Mar 31, 2018

Profile of the example provided by @alshakero

  • 16.2: 16 2
  • 16.3: 16 3

Looks like scheduling is somehow off and leaves idle gaps?

@gaearon
Copy link
Collaborator

gaearon commented Mar 31, 2018

We're spending quite a bit more time in performUnitOfWork (which is the hottest path).
I think this line might be the culprit.

Want to try commenting that line out in the bundle and see if it helps?

@mlazowik
Copy link

@gaearon yep, this is it.

@gaearon
Copy link
Collaborator

gaearon commented Mar 31, 2018

Good. I wonder why. Is it the allocation, the enumeration over a fiber, or changing hidden class of the target itself.

Can you try to set stashedWorkInProgressProperties to {} instead of null here and then do

Object.assign(stashedWorkInProgressProperties, workInProgress);

instead and see if it’s still as bad?

@mlazowik
Copy link

mlazowik commented Mar 31, 2018

stashedWorkInProgressProperties is undefined there, so this errors out.

EDIT: Oh, I see what you want to check. Gimme a sec.

@mlazowik
Copy link

mlazowik commented Apr 1, 2018

@gaearon

if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
    allocStashed();
    copyWIP();
}

function allocStashed() {
    stashedWorkInProgressProperties = {};
}

function copyWIP() {
    Object.assign(stashedWorkInProgressProperties, workInProgress);
}

zrzut ekranu 2018-04-01 o 02 02 49

@gaearon
Copy link
Collaborator

gaearon commented Apr 1, 2018

Seems like it's still quite a lot. I bet we need to preserve the hidden class and explicitly write out all assignments.

@mlazowik
Copy link

mlazowik commented Apr 1, 2018

Hm, maybe it's possible to write a generic function to do that based on type annotations? blazingFastClone

@mlazowik
Copy link

mlazowik commented Apr 1, 2018

@gaearon an ad hoc confirmation that hidden class is the issue:

if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
    stashedWorkInProgressProperties = createFiber(
        workInProgress.tag,
        workInProgress.pendingProps,
        workInProgress.key,
        workInProgress.mode
    );
}

zrzut ekranu 2018-04-01 o 02 44 21

@gaearon gaearon mentioned this issue Apr 1, 2018
3 tasks
@mlazowik
Copy link

mlazowik commented Apr 1, 2018

I forgot to actually copy.

if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) {
    stashedWorkInProgressProperties = createFiber(
        workInProgress.tag,
        workInProgress.pendingProps,
        workInProgress.key,
        workInProgress.mode
    );
    Object.assign(stashedWorkInProgressProperties, workInProgress);
}

This is still slow, but faster than with stashedWorkInProgressProperties = {}.

@gaearon
Copy link
Collaborator

gaearon commented Apr 1, 2018

I tried locally and handwritten version seems pretty fast.

@gaearon
Copy link
Collaborator

gaearon commented Apr 1, 2018

#12510

@gregberge
Copy link
Author

Tested on the original example and it is much better, thanks!

@gaearon
Copy link
Collaborator

gaearon commented Apr 4, 2018

Fixed in 16.3.1.

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.

5 participants