Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

Read the new feature of React17 - heuristic update algorithm


Jun 01, 2021 Article blog


Table of contents


Three days ago, the React team released the first RC version of React17 the biggest feature of which was "No New Features."

So what has the React team been doing for more than a year, from v17 v16

From v15 to v16 the React team spent two years refactoring Stack Reconciler in the source architecture into Fiber Reconciler and it must not have been that simple.

In fact, this version change does have a "new feature" -- replacing the heuristic update algorithm used internally.

It's just that this feature is not aware of the developer.

This article goes on to cover the following:

  • Origin: Why is there an heuristic update algorithm?
  • Status quo: React16's heuristic update algorithm and its shortcomings
  • The future: React17's heuristic update algorithm

Why heuristic update algorithms appear

The operational performance of the framework is the key point that frame designers need to focus on when designing the framework.

Vue uses template syntax to optimize the defined template at compile time.

React pure JS writing is too flexible, leaving him innately deficient in compile-time optimization.

Therefore, React optimization is primarily at runtime.

The pain point of React15

React has been working runtime optimization.

For example, React15 batchedUpdates (bulk updates).

That is, multiple setState in the context of the same event callback function trigger only one update.

However, if a single update is time-consuming, the page will still get stuck (which is common in a large application with a long maintenance time).

This is because React15 update process is synchronized and cannot be interrupted once the update is started until the page is rendered.

To address the problem of page carding caused by long-term thread consumption of synchronous updates, and to explore more possibilities for runtime optimization, React began refactoring and continues to do so today.

The goal of the refactoring is to implement Concurrent Mode

(Recommended tutorial: React tutorial)

Concurrent Mode

The purpose of Concurrent Mode is to implement an interruptable/recoverable update mechanism.

It consists of two parts:

  • A co-engineering architecture
  • Heuristic update algorithm based on co-program architecture

Among them, the co-architecture is Fiber Reconciler implemented in React16

We can interpret Fiber Reconciler as React own Generator

A detailed description of Fiber Reconciler from concept to source code can be found here

The co-architecture allows updates to be interrupted when needed, giving the browser time to complete style layout and style drawing, reducing the appearance of catons (dropped frames).

As the browser enters the next event loop, the co-architecture can resume the interrupt or discard the previous update and restart the new update process.

Heuristic update algorithm is the algorithm that controls how the co-program architecture works.

React16 heuristic update algorithm

What does heuristics for heuristic update algorithms mean?

Heuristics refer to updates that are not scheduled by explicit assignment, but by priority.

The priority comes from the research results of human-computer interaction.

Like what:

The results of human-computer interaction show that:

  • When a user enters content in the input box, they want the input to respond in real time to the input box
  • When data is requested asynchronously, it is acceptable for users to wait a while before displaying the content

Based on this, in React16

更新 priority triggered by the input to the input box > the update priority is triggered when the request data is 更新

Algorithmic implementation In React16、17 this.setState within a component produces a list data structure update within the fiber node update the component.

Where update.expirationTimes is a timestamp-like field that represents priority.

expirationTimes is literally understood as the expiration time.

The closer the value is to the current time, the higher the update priority.

When update.expirationTimes the current time, it means that the update expires and the priority becomes the highest (i.e. synchronization).

Multiple fiber nodes in a fiber tree may have multiple update

Each time Fiber Reconciler schedules an update, one of all update.expirationTimes for all fiber expirationTimes is selected (generally the largest choice) as the priority for this update.

and fiber build the new fiber tree down from the root fiber node.

If a fiber node contains update during the build process, and

update.expirationTimes >= expirationTimes

The change in state corresponding to the update is reflected in this update.

It can be understood that one priority is selected for each update, and the final page renders a snapshot of the update corresponding to that priority.

For example, we have the fiber tree shown in the figure, which has not yet been updated, so there is no fiber tree under construction.

 Read the new feature of React17 - heuristic update algorithm1

When a low-priority update is created in C, the update is scheduled, and the priority selected for this update is low priority.

Start building a new fiber tree (right).

 Read the new feature of React17 - heuristic update algorithm2

At this point, we create a high priority update D.

This interrupts the ongoing low-priority update and restarts the generation of a fiber tree with a high priority.

There are no rendering operations because previous updates have been interrupted, and there is no change in the view (left).

 Read the new feature of React17 - heuristic update algorithm3

This update selects a high priority and C's update is skipped.

When the update is complete, the new fiber tree is rendered into view.

 Read the new feature of React17 - heuristic update algorithm4

Because C is skipped, it is not reflected in the view (left).

Next we trigger a high priority update E.

C although it contains a low-priority update over time his expirationTimes has expired and becomes a high-priority.

 Read the new feature of React17 - heuristic update algorithm5

So this update will have changes to both C E fiber nodes.

When the update is finally complete, the view is as follows:

 Read the new feature of React17 - heuristic update algorithm6

Algorithm defects

Models that measure the size expirationTimes work well if only CPU operations such as interrupting/continuing are considered.

However, expirationTimes model does not meet the IO operation (Delay).

Under this model, high-priority IO tasks (Quests) interrupt low-priority CPU tasks.

Remember, every update is a priority update standard for an entire tree, not just a component, even if the source of the update is actually a component.

expirationTimes model can only distinguish between > and the case of >=expirationTimes

To extend Concurrent Mode capability boundary, a more granular heuristic priority update algorithm is required.

(Recommended tutorial: React Getting Started Instance Tutorial)

React17 heuristic update algorithm

The ideal model is that you can specify any number of priorities at which updates generate a snapshot of the page for update

However, under the existing architecture, there are bottlenecks in the implementation of this scheme.

Under compromise, React17 solution is to specify a continuous priority interval, and each update generates a snapshot of the corresponding page at the priority included in the interval.

This priority interval model is called lanes (lane models).

This is done by using a 31-bit binary to represent 31 possibilities.

  • Each of bit is referred to as a lane (lane) that represents priority
  • A binary number lane lanes is called a lanes and lanes a set of priorities

As you can see from the source code, from the Blue Line all the way down, each bit corresponds to a lane or lanes

 Read the new feature of React17 - heuristic update algorithm7

When update is generated, one of the following priorities is obtained based on React16 same heuristic approach:

export const SyncLanePriority: LanePriority = 17; e xport const SyncBatchedLanePriority: LanePriority = 16; e xport const InputDiscreteLanePriority: LanePriority = 14; e xport const InputContinuousLanePriority: LanePriority = 12; e xport const DefaultLanePriority: LanePriority = 10; e xport const TransitionShortLanePriority: LanePriority = 8; export const TransitionLongLanePriority: LanePriority = 6;

The higher the value, the higher the priority.

Like what:

  • Clicking on the update generated by triggering this.setState in an event callback results in InputDiscreteLanePriority
  • Synchronized update get SyncLanePriority

Next, update looks for unoccupied lane with priority as a clue.

If the current fiber tree already exists and the updated lanes contain the lane update lanes to look for additional lane

For example, InputDiscreteLanePriority lanes to InputDiscreteLanes

The 4th and 5th digits are 1 const InputDiscrete Lanes: Lanes s 0b000000000000000000000000000000110000;

The lanes contain the 4th, 5th, 2 bit bits.

If it is

The fifth position is 1 0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

The fifth lane lane already occupied, and the update can attempt to occupy the latter, that is

The fourth position is 1 0b0000000000000000000000000000000000000000000000000000000000000000

If both lane of InputDiscreteLanes are occupied, the update of the update drops to InputContinuousLanePriority and continues to look for spare lane

The process is like this: there is an open-air car park (lanes) on each floor of the mall (with different priorities) and multiple parking spaces in the car park.

Let's drive to the top floor to find a parking space (lane) and if there is no parking space we will continue to look for it on the next floor.

until a spare parking space is found.

Because lanes can contain multiple lane it is convenient to distinguish between IO operations (DNAs) and CPU operations.

When the build fiber tree enters the build Suspense subtree, the lane of the is inserted into the Suspense selected for this update. lanes

When the build leaves the Suspense subtree, Suspense lane is removed from the lanes of this update.

(Recommended micro-class: React micro-course)

summary

React16 expirationTimes model can only distinguish between >=expirationTimes updated >.

React17 lanes model can select an update interval and dynamically add or subtract priorities to the interval to handle more granular updates.

Here's a look at the new feature of React17 the heuristic update algorithm, which I hope will help you.