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

[WIP] Optimize context by using an object for stateNode #12544

Closed
wants to merge 1 commit into from

Conversation

gaearon
Copy link
Collaborator

@gaearon gaearon commented Apr 4, 2018

I tested a tree view with this, and there appears to be a significant improvement in DEV.

My hypothesis is that stateNode being an object prevents some kind of deopt in the propagation loop where fiber type switches from one with a number stateNode to one with an object stateNode.

Details below.

Self Time

Before

dev

After

dev

Detailed Breakdown

Before

hotness_dev

After

hotness_dev

Summary

Before

screen shot 2018-04-04 at 20 36 05

After

screen shot 2018-04-04 at 20 36 54

Firefox

Before

ff_dev

After

ff_dev


What’s odd is, I haven’t seen a noticeable difference in production builds.
Maybe there’s something GCC does that accidentally mitigates this.

My testing procedure is to make a tree view with 1,000 consumers, and then update the root context 10 times. I tried swapping the bundles here and back a few times, and the difference in DEV consistently reproduces.

@sebmarkbage
Copy link
Collaborator

The benchmark should use something more evenly distributed. It is designed to be fast at traversing through non-context fibers. It is also designed to stop and restart.

Since this is adding a bunch of allocation we should probably measure the memory usage too.

We should also consider whether adding another fiber field would be beneficial.

It’s worth noting that this is also a V8 specific optimization. It might be worse in every other engine. So we should probably test those and think about if it is worth the tradeoff.

// Store the observedBits on the fiber's stateNode for quick access.
workInProgress.stateNode = observedBits;
if (oldProps === null) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Props nullability have had other meanings in the past and doesn't have a defined meaning now but might get one.

What is this meant to test? If it is to test that this is first mount, it should check for current === null, but since this is really just testing whether stateNode is null you might as well just make that explicit (Flow will want you to anyway once we properly type stateNode).

@gaearon
Copy link
Collaborator Author

gaearon commented Apr 4, 2018

I think let's hold off until we have some product code that we can benchmark? Don't want to build something just for this if we'll use it for Relay anyway.

if (oldProps === null) {
workInProgress.stateNode = {bits: observedBits};
} else {
workInProgress.stateNode.bits = observedBits;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will mutate both the current and the workInProgress since they'd share the same object. Generally, that's a big nono because many things can go wrong. We'd have to prove that this can't have those issues and won't get them later somehow.

Copy link
Collaborator Author

@gaearon gaearon Apr 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Been too long since I worked on Fiber. Thanks for catching.

@gaearon gaearon changed the title Optimize context by using an object for stateNode [WIP] Optimize context by using an object for stateNode Apr 4, 2018
@sebmarkbage
Copy link
Collaborator

#12745 is adding another case like this. Perhaps we should use a separate field specifically for V8? 😳

@gaearon gaearon closed this May 23, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants