New Reconciler Infra #6690

Merged
merged 1 commit into from May 11, 2016

Conversation

Projects
None yet
5 participants
@sebmarkbage
Member

sebmarkbage commented May 3, 2016

This is an outline for the new reconciler infrastructure.

I created a noop renderer to have something to get started from.

I split the reconciler folder into old and new, as well as shared. I put shouldUpdateReactComponent in shared as an example of a utility that can easily be shared between both. I plan on breaking out more utilities like these.

Builds on top of #6682

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost May 5, 2016

@sebmarkbage updated the pull request.

ghost commented May 5, 2016

@sebmarkbage updated the pull request.

@gaearon gaearon referenced this pull request May 5, 2016

Closed

New Core Algorithm #6170

@jayphelps

This comment has been minimized.

Show comment
Hide comment
@jayphelps

jayphelps May 5, 2016

Contributor

#6170 doesn't really explain these architecture changes. e.g. high vs. low priority renders, incremental and the how and why. Anywhere I can see the discussions on this or have they thus far been informal and undecided and this PR is just to flesh them out? 👯

Contributor

jayphelps commented May 5, 2016

#6170 doesn't really explain these architecture changes. e.g. high vs. low priority renders, incremental and the how and why. Anywhere I can see the discussions on this or have they thus far been informal and undecided and this PR is just to flesh them out? 👯

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon May 5, 2016

Member

have they thus far been informal and undecided and this PR is just to flesh them out?

Yes, I think this is just @sebmarkbage trying to create a useful proof of concept in a way that makes sense to him. The goals are simple: change React from deep recursive rendering on every change to some kind of scheduling.

The way I understand this PR is the following. For scheduling to work, we need some kind of priority system, or otherwise there is no way for React to know which updates should be processed first. “Low” and “high” is the simplest possible way to describe priorities. We don’t know if more kinds of priorities would be helpful, so starting with two makes sense to me. How they are used is an open question, but it’s easy to imagine some options. For example, we might want to schedule high priority updates for something is interacting with (e.g. pressing a Like button) because UI should be responsive to feedback. On the other hand, rendering loading data might be a lower priority (i.e. it’s better to render a new story in the feed with a small delay than cause an animation happening at the same time to drop frames).

If there is any specific algorithm in mind, it’s in @sebmarkbage’s head, but I think he’s just fleshing out a system capable of rendering existing React components with priorities. There’s really not much to it aside from what I wrote above. The existing reconciler code is deeply OO and relies on recursive dynamic dispatches (e.g. mountComponent() of any composite component causes mountComponent() of whatever it renders to) so it’s hard to shove priorities into the existing system. This is why @sebmarkbage is starting the reconciler from scratch in this PR. It’s not clear how long it will take to get to the feature parity, but we’ll see.

Member

gaearon commented May 5, 2016

have they thus far been informal and undecided and this PR is just to flesh them out?

Yes, I think this is just @sebmarkbage trying to create a useful proof of concept in a way that makes sense to him. The goals are simple: change React from deep recursive rendering on every change to some kind of scheduling.

The way I understand this PR is the following. For scheduling to work, we need some kind of priority system, or otherwise there is no way for React to know which updates should be processed first. “Low” and “high” is the simplest possible way to describe priorities. We don’t know if more kinds of priorities would be helpful, so starting with two makes sense to me. How they are used is an open question, but it’s easy to imagine some options. For example, we might want to schedule high priority updates for something is interacting with (e.g. pressing a Like button) because UI should be responsive to feedback. On the other hand, rendering loading data might be a lower priority (i.e. it’s better to render a new story in the feed with a small delay than cause an animation happening at the same time to drop frames).

If there is any specific algorithm in mind, it’s in @sebmarkbage’s head, but I think he’s just fleshing out a system capable of rendering existing React components with priorities. There’s really not much to it aside from what I wrote above. The existing reconciler code is deeply OO and relies on recursive dynamic dispatches (e.g. mountComponent() of any composite component causes mountComponent() of whatever it renders to) so it’s hard to shove priorities into the existing system. This is why @sebmarkbage is starting the reconciler from scratch in this PR. It’s not clear how long it will take to get to the feature parity, but we’ll see.

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon May 5, 2016

Member

Also, for the record, I don’t understand what Fibers are either yet 😄 . The EffectHandler and EffectTag reminds me of this post by @sebmarkbage about algebraic effects. The gist of “effects” in Eff is that functions can throw “effects” and not just errors, and their callers can “catch” these effects, do something, and then yield back to the child function.

This sounds a lot like what React components want to do. Today, we can say setState() is like an effect because it schedules an update to the system. But we want React components to be able to do more and to provide more ways for children and parent to communicate. This is crucial for supporting layout in React: you want a child to “yield” its size to the parent while rendering so that the parent can use this size to set the child’s position. Some notes on a system like this have been posted in react-future two years ago but this wasn’t being worked on. However, two months ago @sebmarkbage, inspired by effects in Eff, made another prototype of a system that would support layout, also in react-future.

Another example is context: we want context updates to be fast, as it is useful for layout and animations, but the current system involves walking the whole tree to update the context which causes issues like #2517. If context was also an effect, and we built support for effects handled by parent components (or React itself) in React, this would probably get solved as well.

Since we don’t actually have algebraic effects in JavaScript, my guess would be that Fibers are some sort of internal abstraction for connecting functions that “throw” effects directly to the functions that handle them. But this may change any day as @sebmarkbage’s still trying different approaches to see what is minimally needed to implement a scheduling reconciler while ensuring future use cases like layout in React are supported better than in the current model.

I might be totally wrong though!

You might also find this helpful: https://github.com/reactjs/react-basic. Especially https://github.com/reactjs/react-basic#algebraic-effects. This is pretty much a braindump of what @sebmarkbage has been thinking about for the past few months. I think the new reconciler will move closer to this conceptual model of React than the existing one, although of course implementation details will still differ from the conceptual model because we live in a real world. 😄

Member

gaearon commented May 5, 2016

Also, for the record, I don’t understand what Fibers are either yet 😄 . The EffectHandler and EffectTag reminds me of this post by @sebmarkbage about algebraic effects. The gist of “effects” in Eff is that functions can throw “effects” and not just errors, and their callers can “catch” these effects, do something, and then yield back to the child function.

This sounds a lot like what React components want to do. Today, we can say setState() is like an effect because it schedules an update to the system. But we want React components to be able to do more and to provide more ways for children and parent to communicate. This is crucial for supporting layout in React: you want a child to “yield” its size to the parent while rendering so that the parent can use this size to set the child’s position. Some notes on a system like this have been posted in react-future two years ago but this wasn’t being worked on. However, two months ago @sebmarkbage, inspired by effects in Eff, made another prototype of a system that would support layout, also in react-future.

Another example is context: we want context updates to be fast, as it is useful for layout and animations, but the current system involves walking the whole tree to update the context which causes issues like #2517. If context was also an effect, and we built support for effects handled by parent components (or React itself) in React, this would probably get solved as well.

Since we don’t actually have algebraic effects in JavaScript, my guess would be that Fibers are some sort of internal abstraction for connecting functions that “throw” effects directly to the functions that handle them. But this may change any day as @sebmarkbage’s still trying different approaches to see what is minimally needed to implement a scheduling reconciler while ensuring future use cases like layout in React are supported better than in the current model.

I might be totally wrong though!

You might also find this helpful: https://github.com/reactjs/react-basic. Especially https://github.com/reactjs/react-basic#algebraic-effects. This is pretty much a braindump of what @sebmarkbage has been thinking about for the past few months. I think the new reconciler will move closer to this conceptual model of React than the existing one, although of course implementation details will still differ from the conceptual model because we live in a real world. 😄

@sebmarkbage

This comment has been minimized.

Show comment
Hide comment
@sebmarkbage

sebmarkbage May 5, 2016

Member

Fibers as a concept is essentially https://en.m.wikipedia.org/wiki/Fiber_(computer_science) reimplemented in user space.

But yea, I don't really know what I'm doing yet. I have a rough idea.

On May 5, 2016, at 4:47 AM, Dan Abramov notifications@github.com wrote:

Also, for the record, I don’t understand what Fibers are either yet 😄 . The EffectHandler and EffectTag reminds me of this post by @sebmarkbage about algebraic effects. The gist of “effects” in Eff is that functions can throw “effects” and not just errors, and their callers can “catch” these effects, do something, and then yield back to the child function.

This sounds a lot like what React components want to do. Today, we can say setState() is like an effect because it schedules an update to the system. But we want React components to be able to do more and to provide more ways for children and parent to communicate. This is crucial for supporting layout in React: you want a child to “yield” its size to the parent while rendering so that the parent can use this size to set the child’s position. Some notes on a system like this have been posted in react-future two years ago but this wasn’t being worked on. However, two months ago @sebmarkbage, inspired by effects in Eff, made another prototype of a system that would support layout, also in react-future.

Since we don’t actually have algebraic effects in JavaScript, my guess would be that Fibers are some sort of internal abstraction for this pattern of “throwing” effects and having callers handle them. But this may change any day as @sebmarkbage’s still trying different approaches to see what is minimally needed to implement a scheduling reconciler while ensuring future use cases like layout in React are supported better than in the current model.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

Member

sebmarkbage commented May 5, 2016

Fibers as a concept is essentially https://en.m.wikipedia.org/wiki/Fiber_(computer_science) reimplemented in user space.

But yea, I don't really know what I'm doing yet. I have a rough idea.

On May 5, 2016, at 4:47 AM, Dan Abramov notifications@github.com wrote:

Also, for the record, I don’t understand what Fibers are either yet 😄 . The EffectHandler and EffectTag reminds me of this post by @sebmarkbage about algebraic effects. The gist of “effects” in Eff is that functions can throw “effects” and not just errors, and their callers can “catch” these effects, do something, and then yield back to the child function.

This sounds a lot like what React components want to do. Today, we can say setState() is like an effect because it schedules an update to the system. But we want React components to be able to do more and to provide more ways for children and parent to communicate. This is crucial for supporting layout in React: you want a child to “yield” its size to the parent while rendering so that the parent can use this size to set the child’s position. Some notes on a system like this have been posted in react-future two years ago but this wasn’t being worked on. However, two months ago @sebmarkbage, inspired by effects in Eff, made another prototype of a system that would support layout, also in react-future.

Since we don’t actually have algebraic effects in JavaScript, my guess would be that Fibers are some sort of internal abstraction for this pattern of “throwing” effects and having callers handle them. But this may change any day as @sebmarkbage’s still trying different approaches to see what is minimally needed to implement a scheduling reconciler while ensuring future use cases like layout in React are supported better than in the current model.


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost May 7, 2016

@sebmarkbage updated the pull request.

ghost commented May 7, 2016

@sebmarkbage updated the pull request.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost May 10, 2016

@sebmarkbage updated the pull request.

ghost commented May 10, 2016

@sebmarkbage updated the pull request.

+ }
+
+ ReactNoop.render(<Foo />);
+ console.log('Nothing done');

This comment has been minimized.

@sophiebits

sophiebits May 10, 2016

Member

no (unmocked) logs in tests please

@sophiebits

sophiebits May 10, 2016

Member

no (unmocked) logs in tests please

+ return null;
+};
+
+exports.createFiber = function(element : ReactElement) {

This comment has been minimized.

@sophiebits

sophiebits May 10, 2016

Member

Can you pick different names for createFiber and createFiber here? It's confusing.

@sophiebits

sophiebits May 10, 2016

Member

Can you pick different names for createFiber and createFiber here? It's confusing.

@sophiebits

This comment has been minimized.

Show comment
Hide comment
@sophiebits

sophiebits May 10, 2016

Member

Meh, okay.

Member

sophiebits commented May 10, 2016

Meh, okay.

React Fiber Reconciler
This is an outline for the new reconciler infrastructure.

I created a noop renderer to have something to get started from.

I split the reconciler folder into old and new, as well as shared.
I put shouldUpdateReactComponent in shared as an example of a
utility that can easily be shared between both. I plan on breaking
out more utilities like these.

@sebmarkbage sebmarkbage changed the title from RFC: New Reconciler Infra to New Reconciler Infra May 11, 2016

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost May 11, 2016

@sebmarkbage updated the pull request.

ghost commented May 11, 2016

@sebmarkbage updated the pull request.

@sebmarkbage sebmarkbage merged commit cf15788 into facebook:master May 11, 2016

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

@zpao zpao added the semver-major label May 16, 2016

@zpao zpao added this to the 16.0 milestone Jun 1, 2016

@zpao

This comment has been minimized.

Show comment
Hide comment
@zpao

zpao Jun 3, 2016

Member

This (and to a lesser extent the followups) are going to make it tricky to continue cherry-picking into the 15 release due to file moves. Is there any risk in cherry-picking this (and the other fiber changes) as well? It doesn't look like anything in current code has really changed. They aren't part of public modules so seems like it should be pretty safe. We could even exclude the whole fiber/ dir from the package if we want.

Member

zpao commented Jun 3, 2016

This (and to a lesser extent the followups) are going to make it tricky to continue cherry-picking into the 15 release due to file moves. Is there any risk in cherry-picking this (and the other fiber changes) as well? It doesn't look like anything in current code has really changed. They aren't part of public modules so seems like it should be pretty safe. We could even exclude the whole fiber/ dir from the package if we want.

@zpao zpao modified the milestones: 15-next, 16.0 Jun 6, 2016

@zpao zpao added semver-exempt and removed semver-major labels Jun 6, 2016

@zpao

This comment has been minimized.

Show comment
Hide comment
@zpao

zpao Jun 6, 2016

Member

After discussing offline - going to take this and some other PRs in 15. While they are currently built in the same pipeline, they aren't part of our exposed API and thus are exempt from semver rules.

Member

zpao commented Jun 6, 2016

After discussing offline - going to take this and some other PRs in 15. While they are currently built in the same pipeline, they aren't part of our exposed API and thus are exempt from semver rules.

zpao added a commit to zpao/react that referenced this pull request Jun 8, 2016

React Fiber Reconciler (#6690)
This is an outline for the new reconciler infrastructure.

I created a noop renderer to have something to get started from.

I split the reconciler folder into old and new, as well as shared.
I put shouldUpdateReactComponent in shared as an example of a
utility that can easily be shared between both. I plan on breaking
out more utilities like these.
(cherry picked from commit cf15788)

zpao added a commit that referenced this pull request Jun 14, 2016

React Fiber Reconciler (#6690)
This is an outline for the new reconciler infrastructure.

I created a noop renderer to have something to get started from.

I split the reconciler folder into old and new, as well as shared.
I put shouldUpdateReactComponent in shared as an example of a
utility that can easily be shared between both. I plan on breaking
out more utilities like these.
(cherry picked from commit cf15788)

@zpao zpao modified the milestones: 15-next, 15.2.0 Jun 14, 2016

@paulirish paulirish referenced this pull request in acdlite/react-fiber-architecture Aug 7, 2016

Open

Link to key PRs and meeting notes #5

@gaearon

This comment has been minimized.

Show comment
Hide comment
@gaearon

gaearon Jun 8, 2017

Member

It’s not clear how long it will take to get to the feature parity, but we’ll see.

I guess we know that now. 😄

Member

gaearon commented Jun 8, 2017

It’s not clear how long it will take to get to the feature parity, but we’ll see.

I guess we know that now. 😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment