The inner workings of the renderer process

Renderer process

The Renderer Process is responsible for everything that happens to the Tab. In the Renderer Process, the Main Threads Process handles most of the code you write for the user. If you are using a Web worker or service worker, this will be handled by Work Threads. Compositor and Raster Threads also run within the Renderer Process to render pages efficiently and smoothly.

The core job of the Renderer Process is to transform HTML, CSS, and JavaScript into web pages that users can interact with.

Figure 1: Inside the renderer process are the main thread, worker thread, layout thread, and raster thread

Figure 2: WebKit rendering flowchart

parsing

The construction of the DOM

When the renderer process receives THE HTML from the local disk or the browser from the web process, the main thread parses the HTML string and converts it into the DOM — Document Object Model in a sequential and progressive manner.

  • Convert HTML strings into tokens with information such as startTag, endTag, or text.

  • The relationship between child and parent nodes is identified using tokens with identifiers.

Figure 3: Hello appears between title’s starTag and endTag, so Hello belongs to the children of title

  • Consume in turn what is generatedToken, generate node objects and build a DOM Tree

Terminating identifiers do not create node objects

<html>
<head>
    <title>Web page parsing</title>
</head>
<body>
    <div>
        <h1>Web page parsing</h1>
        <p>This is an example Web page.</p>
    </div>
</body>
</html>
Copy the code

The above string of code will eventually generate the following DOM Tree

Figure 4: THE DOM is the internal representation of the page in the browser, as well as a data structure and API that Web developers can interact with through JavaScript.

This is the HTML standard that DOM parsing follows and more details about HTML parsing

Subresource loading

Websites often use external resources such as images, CSS, and JavaScript. These files need to be loaded from the network or cache. The main thread can request them individually as it parses the build DOM, but for speed, the preloaded scanner runs at the same time. If there is something like < IMG > or in the HTML document, the preload scanner checks the markup generated by the HTML parser and sends a request to the network thread in the browser process.

Figure 5: The main thread parses the HTML and builds the DOM tree

JavaScript prevents parsing

When the HTML parser finds the

Figure 6: Javacript causes DOM to be re-rendered

Prompt browser how to load resources

Web developers can send prompts to browsers in a number of ways to load resources nicely. If your JavaScript doesn’t use Document.write (), you can add async or defer properties to the

// lib.mjs
export const repeat = (string) = > `${string} ${string}`;
export function shout(string) {
  return `${string.toUpperCase()}! `;
}

Copy the code
// main.mjs
import {repeat, shout} from './lib.mjs';
repeat('hello');
/ / - > 'hello hello'
shout('Modules in action');
Copy the code
<script type="module" src="main.mjs"></script>
<script nomodule src="fallback.js"></script>
Copy the code

A script tag with the module identifier is treated as a module and does not block page loading.

Figure 7: Schematic of script tag loading

is a way of telling the browser that the current navigation definitely needs the resource, indicating that you want to download it as soon as possible.

Resource priority

Style calculation

Having the DOM is not enough to know what the page looks like, because we can style the page elements in CSS. The main thread parses the CSS and determines the style of each DOM node, using the resulting information to apply the specific style to each DOM node based on the CSS selector. You can look at computed in the developer tools in your browser.

Such as:

.fancy-button {
    background: green;
    border: 3px solid red;
    font-size: 1em;
}
Copy the code

Convert to the following data structure:

Figure 8: The browser converts things like background and border to plain for easy parsing

Any dimensional value is reduced to one of three possible outputs: auto, percentage, or pixel value

Figure 9: Transformed CSS values

Then calculate the weights of each selector:

! Important inline > > ID > > tags | pseudo class | select > > > false object wildcard attribute inheritance

Figure 10: Weight diagram

For styles with the same weight, the later style overrides the previous style.

Browser styles may come from sources other than those provided by the developer:

  • User style: Page zooming and scaling performed by the user.
  • Browser style: The browser has its own style

Permissions are as follows: User Style > Developer Style > Browser Style

Based on the limited permissions and weights of styles, update the calculated styles to CSSOM (CSS Object Model), which is located in Document. stylesheets.

Figure 11: The main thread parses the CSS to add computational styles

Build the Render tree

Now, the renderer process knows the structure of each node’s document and style, but this is not enough to render a page.

Layout is the process of finding element geometry. The main thread iterates through DOM and computed styles and creates a layout tree that contains information such as x and Y coordinates and margin, border, padding, and content. A layout tree can be a similar structure to a DOM tree, but it contains only information related to what is visible on the page.

  • Each node in the Render tree is called a RenderObject.
  • Renderobjects correspond almost one to one with DOM nodes. When a visible DOM node is added to the DOM tree, the kernel generates a RenderOject for it to add to the Render tree.
  • Where, visible DOM nodes do not include:
    • Some nodes do not show up in the render output(< HTML > < script > < link >... .).Will be ignored.
    • display: noneThe nodes of the
  • includingvisibility: hiddenThe elements of the
  • Includes pseudo-class elements such as::before

Figure 12: The main thread traverses the compute style DOM tree and generates the layout tree

Instead of using the Render tree directly, In order to facilitate processing Positioning, Clipping, Overflow – scroll, CSS Transfrom/Opacrity/Animation/Filter, the Mask or Reflection, Z – indexing and other properties, The browser needs to generate another tree: the Layer tree

Renderlayers are generated by browsers for specific RenderObjects as follows:

  • It’s the root object for the page
  • Relative absolute or a transform It has explicit CSS position properties (relative, absolute or a transform)
  • Is It transparent
  • Whether there is overflow, an alpha mask or reflection
  • Is there acssFilter Has a CSS filter
  • Does it contain acanvasButa pile to canvas element that has a 3D (WebGL) context or an accelerated 2D context
  • Does it contain avideoButa pile to a video element

When one of the above conditions is met, the RrenderObject is selected by the browser to generate the corresponding RenderLayer. Renderobjects that are not selected are subordinate to the parent RenderLayer. Finally, each RrenderObject t belongs directly or indirectly to a RenderLayer.

The browser rendering engine traverses the entire Layer tree during layout and rendering, accessing each RenderLayer, traversing the RrenderObject belonging to that RenderLayer, and rendering each RenderObject.

It can be understood as: The Layer tree determines the order in which the page is drawn, and the RrenderObject, which is subordinate to the RenderLayer, determines the content of this Layer. All of the RenderLayer and RrenderObject together determine what the page will render on the screen.

Figure 13: The main thread generates a layer tree by traversing the layout tree

Layout and drawing

When the browser generates the render tree, the layout (also known as backflow) is performed based on the render tree. All the browser has to do at this stage is figure out the exact location and size of each node on the page. This behavior is often referred to as “automatic reordering.”

The main thread traverses the layout tree to create a draw record. The drawing record is a comment on the drawing process, as in “background first, then text, then box”.

The output of the layout process is a “box model” that accurately captures the exact position and size of each element within the viewport, and all relative measurements are translated into absolute pixels on the screen.

Figure 14: The main thread traverses the layout tree and generates draw records

Immediately after the layout is complete, the browser issues “Paint Setup” and “Paint” events that convert the render tree into pixels on the screen.

Updating render channels is expensive

One of the most important things in the rendering process is that at each step, the results of the previous operation are used to create new data. For example, if something in the layout tree changes, the DOM will be redrawn.

Figure 15: DOM + Style, layout and generation order of draw tree

If you want to animate elements, the browser must run these operations between each frame. Most of our monitors refresh the screen 60 times per second (60 FPS); When you change the page within each frame, the animation looks smooth to the human eye. But if the animation misses a frame, the page will flicker or stall.

Figure 16: Animation frames on the timeline

Even if your render operation can keep up with the screen refresh, these calculations are running on the main thread, which means your application may be blocked when it runs JavaScript.

Figure 17: Animation frames on the timeline, but JavaScript blocks one frame

You can break up JavaScript operations into small chunks and arrange them to run on each frame using requestAnimationFrame(). You can also run JavaScript in Web Workers to avoid blocking the main thread.

Figure 18: A smaller JavaScript block running on the timeline of an animation frame

synthetic

How would you draw a page?

Now that the browser knows the structure of the DOM, the style of each element, the geometry of the page, and the order in which it draws the page, how does it draw the page?

Converting this information into pixels on the screen is called rasterization.

Figure 19: Simple rasterization process

An easy way to handle rasterization is to use rasterized portions of the screen inside the viewport first. If the user scrolls the page, the raster window is moved and the missing parts are filled in through rasterization. This is how Chrome handled rasterization when it was first released. However, modern browsers run a more complex process called compositing.

What is composition

Composition is a technique of dividing the parts of a page into several layers, rasterizing them separately and producing the page in a separate synthesizer thread. If scrolling occurs, since the layer is already rasterized, all it has to do is compose a new frame: animate by moving the layer and compose a new frame.

Figure 20: Schematic animation of the composition process

You can use the Browser developer tools “Layout” panel to see how your site is divided into layers

Is divided into several layers

To figure out which elements need to be placed in which layers, the main thread creates a layer tree by iterating through the layout tree

Figure 21: Example of page layering

Common cases of layering a page:

  • 3D transforms:Translate3d and translateZ
  • Video, Canvas, iframeElements such as
  • throughElement.animate()Implementation of theopacityThe animation transformation
  • throughС SSanimatedopacityThe animation transformation
  • position: fixed
  • withwill-changeattribute
  • rightopacity,transform,fliter,backdropfilterThe application ofanimationortransition

Perhaps you want to provide layers for each element, but too many layers to compose can result in a slower operation than rasterizing a small portion of the page per frame, so measuring your application’s rendering performance is critical.

Raster and compound close the main thread

Once the layer tree is created and the drawing order determined, the main thread submits this information to the synthesizer thread. The synthesizer thread then rasterizes each layer. A layer can be as large as the entire length of the page, so the synthesizer thread divides them into blocks and sends each block to the raster thread. The raster thread rasterizes each graph block and stores it in GPU memory.

Figure 22: The raster thread creates the tile bitmap and sends it to the GPU

The synthesizer thread can prioritize different raster threads so that things in (or near) the viewport can be rasterized first. The layer also has multiple blocks for different resolutions to handle things like zoom actions. After rasterization, the synthesizer thread collects block information called “draw rectangles” to create composite frames.

noun explain
Draw a rectangle Contains information such as the location of a block in memory and the location of a block to draw in a block considering page composition
Synthesis of frame A collection of drawing quadrilateral that represents a page frame

The composite frame is then submitted to the browser process via IPC. At this point, another composite frame can be added from the UI thread for browser UI changes, or extensions can be added from other renderer processes. These synthesizer frames are sent to the GPU for display on the screen. If a scroll event occurs, the synthesizer thread also creates another composite frame and sends it to the GPU.

Figure 23: Synthesizer thread creating composite frame.

Frames are sent first to the browser process and then to the GPU. The nice thing about composition is that it doesn’t involve the main thread. The composite thread does not need to wait for style calculations or JavaScript execution. This is why compositing is the best choice for smooth performance. If the layout or drawing needs to be computed again, the main thread must be involved.

The problem