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

Some questions about lanes. #19804

Closed
yisar opened this issue Sep 10, 2020 · 20 comments
Closed

Some questions about lanes. #19804

yisar opened this issue Sep 10, 2020 · 20 comments

Comments

@yisar
Copy link
Contributor

yisar commented Sep 10, 2020

First of all, thank you for reading and patience.

I've been studying the principle of react lanes recently, and its implementation is interesting to me, but I still don't know what the specific problems it solves.

This constraint was designed before Suspense was a thing, and it made some sense in that world. When all your work is CPU bound, there's not much reason to work on tasks in any order other than by their priority. But when you introduce tasks that are IO-bound (i.e. Suspense), you can have a scenario where a higher priority IO-bound task blocks a lower-priority CPU-bound task from completing.

From the explanation of @acdlite , it seems to solve the blocking problem of IO operation on low priority tasks.

But I couldn't figure out what asynchronous IO blocked?

<A/>
<Suspense>
  <B/>
</Susepsne>
<C/>

Based on the above example, before lanes, where is blocked, and where is the problem solved after lanes.

Or do you have a better demo to explain?

For developers, the new technology related information is too little, binary is also very abstract, thank you again for your patience.

@wineSu
Copy link

wineSu commented Sep 10, 2020

me too

@Knove
Copy link

Knove commented Sep 10, 2020

I think it's through lanes that we can better distinguish the two?

@bvaughn
Copy link
Contributor

bvaughn commented Sep 10, 2020

The comment you mention is describing a scenario where React has more than one update scheduled– a high priority and a low priority. React starts rendering the high priority update but then something "suspends" because it needs more data (IO). Even though this update is the highest priority thing for React to work on, there's nothing React can do to make the data load faster, so while it waits– it switches to work on the lower priority update. When the data for the higher priority update returns (e.g. when a fetch or XHR completes) then React can stop working on the lower priority work and resume work on the higher priority work.

The IO-bound scenario described above is different from a CPU-bound scenario, where the only thing preventing React from finishing the update and committing is how fast the CPU can execute your JavaScript while rendering components. In this case, it makes sense for React to keep working on the highest priority update until it finishes.

Our new lanes model makes it easier to model and coordinate these concerns.

Hope this answer was helpful. I'm going to close this issue now!

@bvaughn bvaughn closed this as completed Sep 10, 2020
@gaearon
Copy link
Collaborator

gaearon commented Sep 10, 2020

As a concrete example, here's a snippet of code that behaves differently.

Before Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-p9k1b
After Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-zoqm2

@Knove
Copy link

Knove commented Sep 10, 2020

As a concrete example, here's a snippet of code that behaves differently.

Before Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-p9k1b
After Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-zoqm2

Before Lanes Demo (https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-p9k1b) is a CPU-bound scenario, so I guess, this demo React version is not the @bvaughn say: "while it waits– it switches to work on the lower priority update"?

Hope to get a reply, thank you ! :)

@gaearon
Copy link
Collaborator

gaearon commented Sep 10, 2020

The larger point is that previously Suspended updates prevented any updates of the same or lower priority from completing. Now there is no linear notion of "priority", it's just different lanes that we can work on "simultaneously".

@yisar
Copy link
Contributor Author

yisar commented Sep 11, 2020

Thank you. Now I understand. Thank you very much for your discussion. It is hlepful for me.

@Knove
Copy link

Knove commented Sep 11, 2020

The larger point is that previously Suspended updates prevented any updates of the same or lower priority from completing. Now there is no linear notion of "priority", it's just different lanes that we can work on "simultaneously".

Thank you for your patience.

@NE-SmallTown
Copy link
Contributor

NE-SmallTown commented Sep 11, 2020

As a concrete example, here's a snippet of code that behaves differently.

@gaearon This is very interesting, Dan!

But I'm a bit concerned about this 'feature', because the behavior of the new one(i.e after Lanes) is a 'breaking change'(maybe this word is not exact, sorry). Before(before Lanes), all we know(from the talk or doc) is that the throw trick(react-cache or something similar) in render will block the render of that component until the promise resolved.

But now(after Lanes), this is not true anymore. Now, when the promise be thrown, we will not stop the render, on the contrary, we will do render again but use the previous value of the resource variable(in the demo), after the promise resolved, we will use the fresh value of the resource variable to render.

This behavior is exciting, it makes we can do more lower level of suspense/resuming encapsulation, before it is not possible because the suspended Component is a whole node, you can only render it or don't render it, but now we can just render part of it in real time and left the suspended promise behind as if react can treat all of the nodes/elements which use/read the resolved promise value as a separate Component

Before Lanes: https://codesandbox.io/s/suspense-before-lane-g9woh the console will not output after you click until the promise resolved

After Lanes: https://codesandbox.io/s/suspense-after-lane-8btjx the console will continue output with the previous resource

you can watch the console to get a visible experience

But this is also what I'm concerned :)

@yisar
Copy link
Contributor Author

yisar commented Sep 11, 2020

the throw trick(react-cache or something similar) in render will block the render of that component until the promise resolved.

In fact, in the browser, asynchronous IO should not block anything. The reason why Suspense blocks is because it uses the throw-catch mechanism, its unit is a component. The behavior after lane is more consistent with cognition.

So in fact, the previous behavior was wrong, and now it is better.

@gaearon
Copy link
Collaborator

gaearon commented Sep 11, 2020

Before(before Lanes), all we know(from the talk or doc) is that the throw trick(react-cache or something similar) in render will block the render of that component until the promise resolved.

This is not quite right. Even in the very first demos, you saw that while a component is Suspended on a transition, it’s still interactive. For example we can click on a different item in a list. This is crucial (and has always been) because you don’t want the UI to freeze any time there is an asynchronous operation. At the very least you need to be able to show the pending state.

It would be more correct that what really gets Suspended is the state update itself. But other state updates may still be able to continue rendering. Of course, we can’t skip arbitrary state updates — their order might be important. So we use a heuristic to decide which ones are OK to skip and not wait for. Previously this heuristic was based on a linear concept of a priority. Now it is based on grouping into “lanes”.

@gaearon
Copy link
Collaborator

gaearon commented Sep 11, 2020

In fact the very ability to keep rendering with the previous state while the next update is Suspended is why we’re saying it is concurrent mode. We can think of these two operations as concurrent to each other, and rendering the previous state is how we avoid blocking them on each other.

@NE-SmallTown
Copy link
Contributor

NE-SmallTown commented Sep 11, 2020

It would be more correct that what really gets Suspended is the state update itself.

@gaearon I'm sorry I used the word 'block', yes, I just mean that the render of the suspended component will not be triggered, but sure, we can still interact with the page/UI

We can think of these two operations as concurrent to each other

Yes! That's why I said "as if react can treat all of the nodes/elements which use/read the resolved promise value as a separate Component"

This is a big step to bring us to the real concurrent world of UI

and rendering the previous state is how we avoid blocking them on each other.

But this is a "big" step too, why we decide to use/add this behavior at now rather than before? It's a big change from my personal perspective(and I don'n know whether someone depend on the previous behavior), I guess all you had discussed/talked much about this before? I would be very happy if you can share something about this if it exist

@gaearon
Copy link
Collaborator

gaearon commented Sep 11, 2020

I just mean that the render of the suspended component will not be triggered, but sure, we can still interact with the page/UI

This is not correct. Even before, if a component Suspends (at a low priority), its render would still run (if a high priority state update happens). There is no other way to keep the UI interactive! The change is only in how we do the grouping.

@NE-SmallTown
Copy link
Contributor

NE-SmallTown commented Oct 9, 2020

@gaearon Sorry for late response for busy.

its render would still run

Yea, the render method will be called but all the statements after resource.read(...) will not be executed(just like it not renders), that's why I said "the render of the suspended component will not be triggered". (Maybe this misled you but my meaning was not the render method won't be called)

I can't find your online iceland demo, but I find a similar repo, you can see that the console.log("real render"); will not be printed when you click one or a few items in sequence.

There is no other way to keep the UI interactive

When you have clicked a item and then it suspend, you can still click other items(in above demo) and the item will show a spinner(before delayMs reached), that's why I said "but sure, we can still interact with the page/UI"

@yisar
Copy link
Contributor Author

yisar commented Oct 10, 2020

Here is a good summary

First of all, in my opinion, the problem to be solved is resumable exception, which comes from the blocking of JS logic by try catch. We want to break the blocking.

From the current implementation point of view, it is actually implemented with the help of state machine and rescheduling, which should be called concurrent.

try {
  updateComponent()
} catch(e) {
  if (typeof e.then === 'function') reschedule(workingInProgress)
}

But I wonder if there is a better way to recover exceptions without rescheduling (at least the component does not need to be rerendered)?

This should be a common goal for some time to come.

@gaearon
Copy link
Collaborator

gaearon commented Oct 10, 2020

I think we’re going very off topic here. If you have general questions about Suspense feel free to file a more concrete issue.

@yanlee26
Copy link

yanlee26 commented Jan 12, 2022

As a concrete example, here's a snippet of code that behaves differently.

Before Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-p9k1b After Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-zoqm2

talk is cheap, while the first one not work!

@wine-fall
Copy link

As a concrete example, here's a snippet of code that behaves differently.

Before Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-p9k1b After Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-zoqm2

Those two demos can't work now.

@L1atte
Copy link

L1atte commented Apr 9, 2023

As a concrete example, here's a snippet of code that behaves differently.
Before Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-p9k1b After Lanes: https://codesandbox.io/s/usetransition-stop-reacting-passed-props-updates-zoqm2

Those two demos can't work now.

It work for me.
You can remove the dependencies about the react and react-dom, and then install the lastest one.

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

No branches or pull requests

10 participants