Chrome browser architecture

Chrome browser architecture

background

\

This article was included in the column of browser working principle in my series of articles on front-end technology. As the first article of this column, let s start with the most common problem of how the page is displayed in the browser. At the beginning, an overall introduction to the working principle of the browser. This article is based on Mariko Kosaka 's Inside look at modern web browser series of articles published in the Chrome developer documentation in September 2018, combined with my own understanding. If you are concerned about how the browser converts the code into a page, this is for you.

\

CPU and GPU

\

As the two most important computing units in a computer, CPU and GPU directly determine computing performance.

\

CPU

CPU.png

The CPU is the brain of the computer and is responsible for processing various tasks. In the past, most CPUs were single-chip, and the cores were placed on the same chip. The newer CPU can support multiple cores, and the computing power is greatly enhanced. The latest cpu has reached the capacity of 10 cores and 20 threads.

\

GPU

GPU.png

The GPU is another component of the computer. Unlike the CPU, the GPU is better at using multiple cores to process a single task at the same time. As named, the GPU was originally used to process images. This is why using GPU can render page content faster and smoother. With the development of GPU, more and more computing tasks can also be processed by GPU. Some people even say that GPU is a great contributor to artificial intelligence, which shows that GPU is no longer only used for image processing.

\

Computer architecture

\

hw-os-app.png

We can divide the computer into three layers from bottom to top: hardware, operating system, and application. With the existence of the operating system, applications running on the upper layer can use the hardware resources provided by the operating system without directly accessing the hardware resources.

\

Process and thread

\

process-thread.png

A process is a program that the application is running. The thread is a smaller part of the process. When the application is launched, the process is created. The program can create threads to help its work. The operating system will allocate private memory space for the process for use, and when the program is closed, this private memory will also be released. In fact, there is a coroutine that is smaller than a thread , and a coroutine is a smaller unit that runs in a thread. async/await is implemented based on coroutines.

\

Inter-process communication (IPC)

\

\

One process allows the operating system to start another process to handle different tasks. When two processes need to communicate, IPC (Inter Process Communication) can be used.

\

Most programs are designed to use IPC to communicate between processes. The advantage is that when a process sends a message to another process without responding, it does not affect the current process to continue working.

\

Browser architecture

\

With the help of processes and threads, the browser can be designed as a single-process, multi-threaded architecture, or use IPC to achieve a multi-process, multi-threaded architecture.

\

browser-arch.png

Here we introduce the Chrome multi-process architecture. There are different types of processes in Chrome, and they each perform their duties.

\

browser-arch2.png

The browser process, as the core process in Chrome, manages other processes in Chrome, and the Renderer is responsible for rendering different sites.

\

Process work content

\

browserui.png

\

Browser process

The browser process is responsible for managing the Chrome application itself, including the address bar, bookmarks, forward and back buttons. At the same time, it is also responsible for invisible functions, such as network requests, file access, etc., as well as the scheduling of other processes.

\

Renderer process

The rendering process is responsible for the rendering of the site, which also includes the running of JavaScript code and the management of web workers.

\

Plugin process

The plug-in process is responsible for providing various additional plug-in functions for the browser, such as flash.

\

GPU process

The GPU process is responsible for providing imaging functions.

\

Of course, there are other processes such as extension processes or tool processes, which can be viewed in the Task Manager panel of Chrome. The panel lists the running processes and the CPU and memory occupied by them.

\

Benefits of multi-process architecture

\

When we visit a site, the rendering process will be responsible for running the code of the site, rendering the pages of the site, and responding to user interaction. When we open three tabs in Chrome to visit three sites at the same time, if one of them does not respond , We can close it and use other tabs. This is because Chrome creates an independent rendering process for each site to handle the rendering of the current site. If all pages are running in the same process, when one page does not respond, all pages are stuck.

\

tabs.png

Another advantage is that with the help of the operating system's control of process security, the browser can place the page in the sandbox, and the code of the site can run in an isolated environment to ensure the security of the core process.

\

Although the multi-process architecture is better than the single-process architecture, because the processes have their own private memory, take the rendering process as an example. Although the rendering sites are different, the work content is roughly similar. In order to complete the rendering work, they will be in their own memory. Contains the same functions, such as the V8 engine (used to parse and run Javascript), which means that the same functions in this part need to occupy the memory space of each process. In order to save memory, Chrome limits the maximum number of processes. The maximum number of processes depends on the capabilities of the hardware. At the same time, when using multiple tabs to visit the same site, the browser will not create a new rendering process .

\

Service Oriented Architecture

\

Chrome changed its architecture from a multi-process model to a service-oriented model. The browser provides functions as a service to solve the problems in the multi-process architecture.

\

When Chrome runs on a computer with powerful hardware, a service will be implemented in multiple processes to improve stability. When the computer hardware resources are tight, you can put multiple services in one process to save resources.

servicfication.png

\

Rendering process based on site isolation

\

Using iframes, we can access the resources of different sites on the same page, but from a security perspective, the same-origin policy does not allow a site to access the resources of other sites without consent, so starting from Chrome 67, each site is controlled by Independent rendering process processing is enabled by default.

\

isolation.png

\

Browser process

browserprocesses.png

The browser process is responsible for most of the work except rendering. The browser process includes several threads:

  • The UI thread is responsible for drawing the buttons, address bar, etc. in the toolbar.
  • The network thread is responsible for obtaining data from the network.
  • The storage thread is responsible for functions such as files.

\

When we enter an address in the address bar, the UI thread in the browser process is the first to learn about this action and start processing.

\

One visit

\

Let's start with a common visit and gradually understand how the browser displays the page.

Step 1: Input processing

\

When we type in the address bar, the UI thread will first determine whether the content we enter is what we want to search or visit a site, because the address bar is also a search box.

input.png

\

Step 2: The visit begins

\

When we press Enter to start the visit, the UI thread will use the network thread to access the site resources. The loading icon will appear on the title of the browser tab, and the network thread will follow the appropriate network protocol, such as DNS lookup and TLS. This time a connection is requested.

navstart.png

When the server returns a redirect request to the browser, the network thread will notify the UI thread that it needs to be redirected, and then start requesting resources with the new address.

\

Step 3: Process response data

response.png

\

When the network thread receives data from the server, it will try to get the data type ( Content-Type ) from the first bytes in the data to try to understand the format of the data.

\

When the returned data type is HTML, the data will be passed to the rendering process for further rendering work. But if the data type is a zip file or other file format, the data will be passed to the download manager for further file preview or download work.

sniff.png

Before starting to render, the network thread must first check the security of the data. This is where the browser guarantees security. If the returned data comes from some malicious site, the network thread will display a warning page. At the same time, the Cross Origin Read Blocking (CORB) strategy will also ensure that cross-domain sensitive data will not be passed to the rendering process.

\

Step 3: Rendering process

\

When all the checks are over and the network thread is sure that the browser can access the site, the network thread informs the UI thread that the data is ready. The UI thread will find a rendering process based on the current site to complete the next rendering work.

findrenderer.png

In the second step, when the UI thread passes the request address to the network thread, the UI thread already knows the site to visit. At this point, the UI thread can start to find or start a rendering process. This action is simultaneous with letting the network thread download data. If the network thread obtains the data as expected, the rendering process can already start rendering. This action reduces the time from when the network thread starts requesting data to when the rendering process can start rendering the page. Of course, if there is a redirect request, the pre-initialized rendering process may not be used, but compared to the normal site visit scene, redirection is often a small number. In actual work, it also needs to be given according to a specific scene. To come up with a specific plan, you do not have to pursue a perfect plan.

\

Step 4: Submit access

\

After going through the previous steps, the data and rendering process are ready. The browser process will submit this access to the rendering process through IPC, and it will also ensure that the rendering process can continue to obtain data through the network thread. Once the browser process receives the confirmation message from the rendering process, it means that the access process is over and the document rendering process begins.

\

At this time, the address bar displays an icon indicating security, and at the same time displays information about the site. The current site information will also be added to the visit history. In order to restore the access history information, when the tab or window is closed, the access history information will be stored in the hard disk.

commit.png

Extra Step: loaded

\

When the access is submitted to the rendering process, the rendering process will continue to load page resources and render the page. When the rendering process "ends" the rendering work, it will send a message to the browser process. This message will be sent after all subpages (frames) in the page have finished loading, that is, after the onLoad event is triggered. When the "end" message is received, the UI thread will hide the loading status icon on the tab title, indicating that the page is loaded.

\

But "end" here does not mean that all loading work is over, because there may be JavaScript loading additional resources or rendering new views.

loaded.png

\

Visit different sites

\

This is the end of an ordinary visit. When we enter another address, the browser process will repeat the above process. But before starting a new visit, it will confirm whether the current site cares

beforeunload
event.

\

beforeunload
The event can remind the user whether to visit the new site or close the tab. If the user refuses, the new visit or close will be blocked.

\

Since all the work including rendering and running Javascript takes place in the rendering process, the browser process needs to confirm with the rendering process whether the current site cares before the new visit starts.

unload
.

beforeunload.png

If a visit is initiated from a rendering process, such as the user clicking a link or running JavaScript code

location ='http://newsite.com'
When the rendering process first checks
beforeunload
. Then perform the same steps as the browser process to initiate access, but the difference is that such an access request is initiated by the rendering process to the browser process.

\

When a new site request is created, a separate rendering process will be used to process the request. In order to support something like

unload
The old rendering process needs to maintain the current state. For a more detailed introduction to the life cycle, please refer to Page lifecycle .

unload.png

\

Service worker

\

Service worker is a technology that allows web developers to control caching. If the Service worker is implemented to retrieve data from local storage, the original request will not be sent to the server by the browser.

\

It is worth noting that the code in the Service worker is running in the rendering process. When the access starts, the network thread will check according to the domain name whether there is a Service worker that will process the request for the current address. If so, the UI thread will find the corresponding rendering process to execute the code of the Service worker, and the service worker can let the developer decide this Whether the request is to obtain data from local storage or from the network.

scope_lookup.png

\

serviceworker.png

\

Access preload

\

If the service worker finally decides to get data from the network, we will find that this kind of cross-process communication will cause some delay. Navigation Preload is an optimization mechanism that can load resources at the same time as the service worker starts. With the help of special request headers, the server can decide what content to return to the browser.

\

navpreload.png

\

The rendering process is responsible for the content of the page

\

The rendering process is responsible for everything that happens in the browser tab. In a rendering process, the main thread is responsible for parsing, compiling or running code, etc. When we use Worker, the Worker thread is responsible for running part of the code. The compositing thread and the raster thread are also running in the rendering process, and are responsible for more efficient and smooth rendering of the page.

\

The most important job of the rendering process is to convert HTML, CSS and Javascript code into a page that can interact with the user.

renderer.png

Parsing process

\

The following chapters mainly introduce how the rendering process converts the text obtained from the network thread into an image.

\

DOM creation

\

When the rendering process receives the message from the browser process to submit access, it starts to accept HTML data, and the main thread begins to parse the HTML text string and convert it into the Document Object Model (DOM) .

\

DOM is a kind of data used in the browser to express the structure of the page. It also provides an interface for web developers to manipulate page elements, allowing web developers to obtain and manipulate the elements of the page in Javascript code.

\

The standard for converting HTML text into DOM is defined by the HTML Standard . We will find that the browser never throws an exception during the conversion process, such as the loss of the closing tag, the mismatching of the opening and closing tags, etc. This is because the HTML standard defines to handle these errors silently. If you are interested in this, you can read An introduction to error handling and strange cases in the parser .

\

Loading of additional resources

\

A website usually uses additional resources such as images, style files, and JavaScript codes. These resources also need to be obtained from the network or cache. The main thread should load them one by one during the process of converting HTML, but in order to improve efficiency, the preload scan (Preload Scanner) and the conversion process will run at the same time. When the preload scan finds tags like img or link during the analysis of HTML in the analyzer, it will send a request to the network thread of the browser process, and the main thread will decide whether to block the conversion process based on whether these additional resources will block the conversion process. Wait for the resource to load.

dom.png

\

JavaScript will block the conversion process

\

When the HTML parser finds

<script>
When tagging, the next HTML conversion work will be paused, and then the Javascript code will be loaded, parsed, and run. Because in the Javascript code may use something like
document.write
Such an API changes the structure of the DOM. This is why the HTML parser must wait for the Javascript code to finish before continuing the analysis.

\

Tell the browser how to load resources

\

If our Javascript code does not need to change the DOM, it can be

<script>
Tag addition
async
or
defer
Attribute, so that the browser will load these resources asynchronously and will not block the HTML conversion process. If the script tag is created by JavaScript code, the async attribute of the tag will default to true. At the same time, we can also use some pre-loading techniques, such as
<link ref="preload">
To inform the browser that these resources need to be downloaded as soon as possible.

\

Style calculation

\

For displaying a page, DOM alone is not enough, because we also need styles to make the page more beautiful. The main thread will parse the style (CSS) and determine the style of each DOM element. These styles depend on the scope of the CSS selector, and we can see this information in the browser developer tools.

computedstyle.png

Even if we don t assign any styles to the DOM,

<h1>
Label will be better than
<h2>
The label is displayed large. This is because the browser has built-in different styles for different tags. These default styles can be obtained through the Chromium source code .

\

Layout

\

After completing the style calculation, the rendering process already knows the structure of the DOM and the style of each node, but it is still not enough to render a page. Imagine asking you to describe a picture to your friend on the phone: "There is a big red circle and a small blue square in the picture" is not enough to let your friend know what this picture looks like.

tellgame.png

Layout is the process of assigning geometric information to elements. The main thread traverses the elements and their styles in the DOM structure, and at the same time creates a layout tree with coordinates and element size information. The structure of the layout tree is very similar to the structure of the DOM tree, but only contains the elements that will be displayed on the page. When the style of an element is set to display: none, the element will not appear in the layout tree, but those elements whose style is set to visiblility: hidden will appear in the layout tree. Similarly, when we use a pseudo-element that contains content (e.g.

p::before {content:'Hi!'}
), the element will appear in the layout tree even if the element does not exist in the DOM tree. This is why we cannot get the pseudo-element using the API provided by the DOM .

layout.png

Describing page layout information is a challenging task. Even in a page with only block elements, you must consider the font size and where to wrap, because you need to know the size and size of the previous element when calculating the position of the next element. shape.

\

CSS can make the element float, can make the element overflow in the parent element, can change the direction of the text. It is conceivable how arduous it is at this stage of layout. In Chrome, an entire team is working on maintaining the layout, and more detailed information can be viewed in the video .

\

Paint

drawgame.png

With the DOM, styles and layout, rendering can't be done. Just imagine, when we try to copy a picture. We know the size, shape, and position of the elements in the drawing, and we also need to know the order in which these elements are drawn.

\

For example, when the z-index property of an element is set, the order of drawing will cause the rendering to be the wrong result.

zindex.png

At this stage, the main thread traverses the layout tree and creates a drawing record. The drawing record is a series of drawing steps, such as drawing the background first, then the text, and then the shape.

paint.png

\

The rendering process is expensive

\

In the rendering process, the data changes produced in any step will cause a series of subsequent changes. For example, when the layout tree changes, draw the changed part of the page that needs to be reconstructed.

\

When some elements are animated, the browser needs to draw these elements in every frame. When the continuity of each frame drawing cannot be guaranteed, the user will feel stuck.

pagejank1.png

\

Normally, the rendering operation can be synchronized with the screen refresh, but because these operations run in the main thread, it means that these operations may be blocked by the running Javascript code.

pagejank2.png

\

In order not to affect the rendering operation, we can optimize the Javascript operation into small pieces, and then use

requestAnimationFrame()
For how to optimize, please refer to Optimize JavaScript Exectuion . When you need a lot of calculations, you can also use Worker to avoid blocking the main process.

raf.png

\

Compositing

\

Now, the browser already knows the document structure, the style of each element, the geometric information of the elements, and the drawing order. The process of converting this information into pixels on the screen is called rasterization, and rasterization is the category of graphics.

rasterizing.gif

The traditional approach is to rasterize the content of the visible area. As the user scrolls through the page, more areas are continuously rasterized. However, for modern browsers, there is a more complicated process, which is called synthesis.

composit.gif

Composition is a technology that splits a page into multiple layers. The composition thread can rasterize each layer in different threads and combine them into one page. When scrolling, if the layer has been rasterized, the existing layer will be used to compose a new frame, and the animation can be realized by moving the layer.

\

Layer

\

In order to decide which elements the layer contains, the main thread needs to traverse the layout tree to find the parts that need to be generated. For developers, when a certain part needs to be rendered in a separate layer, we can use the css attribute

will-change
Let the browser create the layer, and you can consult the standards on how the browser generates the layer.

\

layer.png

Although the performance of the browser can be optimized through layering, it does not mean that each element should be given a layer. Too many layers will affect the performance. Therefore, the division of layers should be analyzed in detail.

\

Grid thread and synthetic thread

\

When the layout tree and drawing order are determined, the main thread will submit this information to the compositing thread. The compositing thread rasterizes the layers. The content of a layer may be a complete page or part of the page, so the composition thread splits the layer into many blocks and sends them to the grid thread. The raster thread rasterizes these blocks and stores them in the GPU cache.

raster.png

The composition thread can determine the priority of the raster block of the raster thread, so that the part that the user can see can be rasterized first. A layer will also contain multiple blocks to support functions like zooming.

\

When the block is rasterized, the compositing thread uses draw quads to collect this information and create a composite frame (Compositor frame).

\

Draw quads

It is stored in the cache and contains information such as the location of the block, which is used to describe how to use the block to synthesize a page.

Compositor frame

It is used to store the collection of which Draw quads are contained in a frame of the presentation page.

\

Then a composite frame is submitted to the browser process. At this time, if the browser UI changes, or the plug-in UI changes, another composite frame will be created. So whenever there is an interaction, the compositing thread will create more composite frames and then render the new part through the GPU.

composit.png

The advantage of composition is that it is independent of the main thread. The compositing thread does not need to wait for the style calculation and Javascript code to run. This is why composition is more suitable for optimizing interactive performance, but if the layout or drawing needs to be recalculated, the main thread must participate.

\

Essentially, the rendering process of the browser is the process of converting text into images, and when the user interacts with the page, a new image is displayed. In this process, the main thread in the rendering process completes the calculation work, and the synthesis thread and the grid thread complete the image drawing work. In the calculation process, there are more detailed concepts such as forced layout, rearrangement, and redrawing, which will be explained in a later article.

\

View events from the perspective of the browser

\

When we hear events, we usually think of typing in a text box or clicking the mouse, but from the perspective of the browser, input events mean all user actions. Mouse wheel scrolling or screen touch are input events.

\

When the user interacts with the page, the browser process first receives the event. However, the browser process only cares about which tab the event occurred in, so the browser process will send the event type and location information to the responsible person for the current page Signed rendering process, the rendering process will properly find the element where the event occurred and trigger the event listener.

input (1).png

\

Processing of events by synthetic threads

\

In the previous chapters, we learned that the compositing thread can synthesize different raster layers to optimize performance through compositing technology. If the page does not listen to any events, the compositing thread can generate new composite frames completely independent of the main thread. But what if the page listens for events?

\

Mark the "slow scrolling" area

\

Since running Javascript is the work of the main thread, when the page has been synthesized by the synthesis thread, the synthesis thread will mark those areas with event monitoring. With this information, when an event occurs in the response area, the compositing thread will send the event to the main thread for processing. If it is in a non-event listening area, the rendering process directly creates a new frame without caring about the main thread.

nfsr1.png

\

Mark at event listening

\

The common way in web development is event proxy. Using event bubbling, we can listen to events in the upper element of the target element. Refer to the code below.

\

Document .body.addEventListener ( 'touchstart' , Event => { IF (event.target === Area) {the event.preventDefault ();}}); duplicated code

Copy code

\

Through this way of writing, you can monitor events more efficiently. But from the perspective of the browser, the entire page will be marked as a "slow scrolling" area at this time. This means that although some parts of the page do not require event monitoring, the composition thread still has to wait for the main thread to process the event after each interaction, and the optimization effect of the composition thread no longer exists.

nfsr2.png

In order to solve this problem, we can pass in the event agent

passive: true
(IE does not support) parameters. This tells the rendering thread that the event still needs to be sent to the main thread for processing, but there is no need to wait.

\

Document .body.addEventListener ( 'touchstart' , Event => { IF (event.target === Area) the event.preventDefault {()}}, { passive : to true }); duplicated code

Copy code

\

For using passive to improve scrolling performance, you can refer to MDN Using passive to improve scrolling performance .

\

Find event target

\

hittest.png

\

When the rendering thread sends the event to the main thread, the first thing is to find the target of the event. Through the drawing information generated in the rendering process, the target element can be found according to the coordinates.

\

Reduce the number of events sent to the main thread

\

In order to ensure smooth animation, the display needs to be refreshed 60 times per second. For typical touch events, the frequency of events submitted by the synthesis thread to the main thread can reach 60-120 times per second, and for typical mouse events 100 times per second. The frequency of event sending is usually higher than the screen refresh frequency.

\

If similar

touchmove
Sending such an event to the main thread 120 times per second may cause the main thread to take too long to execute and affect performance.

\

rawevents.png

In order to reduce the number of events sent to the main thread, Chrome incorporates consecutive events. similar

wheel
,
mousewheel
,
mousemove
,
pointermove
,
touchmove
Such an event will be delayed until the next time
requestAnimationFrame
Trigger before.

\

coalescedevents.png

\

And any discrete event, similar to

keydown
,
keyup
,
mouseup
,
mousedown
,
touchstart
with
touchend
Will be sent to the main thread for processing immediately.

\

summary

\

At this point, we can already understand how the browser works from the user's input in the browser address bar to the display of the page image. Here we summarize.

\

  • As the most important process, the browser process is responsible for most of the external work of the tab, including address bar display, network request, tab status management, etc.
  • Different rendering processes are responsible for the rendering of different sites, and the rendering processes are independent of each other.
  • The rendering process will obtain site resources through the browser process during the process of rendering the page, and only safe resources will be received by the rendering process.
  • In the rendering process, the main thread is responsible for most of the work except for image generation. How to reduce the code running on the main thread is the key to optimization of interactive performance.
  • The synthesis thread and raster thread in the rendering process are responsible for image generation, and the efficiency of image generation can be optimized by using layering technology.
  • When the user interacts with the page, the propagation path of the event is from the browser process to the composition thread of the rendering process and then decides whether to pass it to the main thread of the rendering process according to the area where the event is monitored.

\

In this column, there will be more detailed explanations on the topic of how the browser works, including page circulation system, V8, network, etc., so stay tuned.

\

Finally, thank you for reading.

\