preface

This article introduces the concept of a Frame in a browser and how it works.

The starting point for this article was that I was curious about what the pixel workflow in the browser looked like, when it started, and what the end result would be.

Based on these curiosity, looked up some foreign language materials, this paper provides some references, reference links at the end of the article.

Recently developed a performance optimization mind map, which is still being output, click here

The reason

Before we talk about frames, we need to start with the background, the process of rendering the page, and what are the key paths.

Five key render paths

Pixel output to the page must go through a lot of processes, so as front-end engineers, we need to pay attention to what points in the work, here for reference:

These five main areas should be the ones we pay attention to because we have the most control over. As for the details of each process, please refer to the following figure if it is not clear:

Therefore, in such a pixel pipeline, every part may cause lag, so we need to pay extra attention to these, after all, that part of the improper, will be unnecessary performance overhead.

Three output modes

My question at the time was: Does every frame always go through every part of the pipeline? Well, it doesn’t. Visually, there are usually three ways the pipeline works for a given frame:

If we update the view in a third way, changing a property that neither layouts nor draws, the browser will jump to just perform composition.

Run a demo

To more concretely verify the above process, run a demo to verify it.

The demo address: googlechrome. Making. IO/devtools – sa…

We added several DOM elements to animate the Performance, Record process, we need to focus on the Main TAB, which is the Main thread, we zoom in on the Task, we have the following image:

Update Layer Tree –>> Layout –> Paint –>> Composite Layers.

If you’re not sure what a name means in Performance, you can refer to the following article, click here:

Mp.weixin.qq.com/s/iodsGPWgY…

Then, we pressed the Optimize button, followed the previous process, Record, found something wrong, or the same steps, is there a problem, CURIOUS ME, opened the Sources panel, and found:

Its source optimization animation, the use of rAF, understand the people must not be strange, you can simply understand is: according to the frame of the web page to redraw. This brings us to the concept of frames, which will be explained later.

Detailed introduction of rAF, it will be sorted out in the follow-up, can continue to pay attention to.

How to avoid backflow and redraw

To get back to our point, how can we make sure that we skip to composition without Layout and Paint? Of course, we need to transform the uppdate function in app.js using transform: translateX(0px); After doing the animation and finishing the processing logic of the update function, let’s Record again:

From the Task subtask, we can see that Layout ->> Paint, Layout and drawing are skipped. This is why we often talk about avoiding backflow and repainting. From the main thread point of view, can completely avoid these processes, avoid a lot of computing overhead.

That’s why it’s common to see advice like this:

  • Do use transform and opacity property changes for animation.
  • usewill-changetranslateZPromote moving elements.

As for using will-change and translatez to raise layers, this is another topic.

So far, we have clearly understood the meaning of avoiding backflow and redrawing, so how do we relate frames and rAF to render paths?

frame

The first thing I did was Google, and Wikipedia came up with the following definition:

In the field of video, film, television, digital video, etc., can be regarded as a number of pictures changing continuously over time, in which frame refers to each picture.

Well, it wasn’t clear until I found this picture that my puzzle was solved:

This is really a picture worth a thousand words.

In this picture, you can see that achievement is the whole process of putting pixels on the screen. You must be confused by some of the key information, here are some explanations.

Next most of the content is translated, there is no more summary, interested can look at the original.

The PROCESSES (process)

What comes into view is progress:

  • Renderer Process: render process.
    • A label around the container.
    • It consists of multiple threads that work together to make your page appear on the screen.
    • These threads are Compositor, Tile Worker, and main thread.
  • GPU Process: GPU process.
    • This is a single process that serves all the tabs and the surrounding browser processes.
    • When the frame is submitted, the GPU process will upload any tiles and other data (such as four-dimensional vertices and matrices) to the GPU in order to actually push the pixels onto the screen.
    • A GPU process consists of a single thread, called a GPU thread, that actually does the work.

RENDERER PROCESS THREADS

Now let’s look at threads in the Renderer Process.

  • Compositor Thread(Composite thread):
    • This is the first thread to be told about the vsync event (which is how the operating system tells the browser to make a new frame).
    • It will also receive any input events.
    • If possible, the synthesizer thread will avoid entering the main thread and will try to convert the input (say, a scroll swing) to on-screen motion. This will be done by updating the layer position and submitting the frame directly to the GPU via the GPU thread.
    • If this is not possible because of input event handlers or other visual work, the main thread is used.
  • Main Thread(The main thread) :
    • This is where browsers perform tasks we all know and love. JavaScript, styles, layouts, and painting. (In future Houdini iterations, this will change and we will be able to run some code in Compositor threads.)
    • This thread wins the “most likely to cause Jank” award, mainly because there’s a lot going on here. (Jank is worth page jitter)
  • Compositor Tile Worker(s) (Synthesize blocks to rasterize threads) :
    • One or more threads derived from a composite thread for handling rasterization tasks. We’ll talk about that later.

In many ways, you should think of the Compositor thread as the “big boss”. While it doesn’t run JavaScript, Layout, Paint, or anything else, it is entirely responsible for starting the main thread and then shipping the frames to the screen. If it doesn’t have to wait for an input event handler, it can ship frames while waiting for the main thread to finish its work.

You can also imagine Service Workers and Web Workers living in this process, though I’m not including them because it makes things more complicated.

THE FLOW OF THINGS

Let’s start with the main thread.

Let’s walk through the process step by step, from Vsync to pixels, and talk about how things work in the “full fat” version of events. It’s worth remembering that the browser doesn’t need to perform all of these steps, depending on what is necessary. For example, parsing HTML will not start if there is no new HTML to parse. In fact, many times, the best way to improve performance is simply to eliminate the need for part of the process to be started!

Also note that the red arrow under the style and layout appears to point to the requestAnimationFrame. It is entirely possible to accidentally trigger both in your code. This is known as forcibly synchronized layouts (or styles, as the case may be), and it is often not good for performance.

  1. Frame Start:

    1. A vSYNC signal is triggered to start rendering a new frame.

  2. Input Event Handlers.

    1. – Input data is passed from the synthesizer thread to any input event handler on the main thread.

    2. All input event handlers (touch move, scroll, click) should start first, once per frame, but this is not necessarily the case.

    3. The scheduler tries its best, and the success rate varies between operating systems. There is also some delay between the user interaction and the event entering the main thread processing.

  3. RequestAnimationFrame:

    1. This is an ideal place to visually update the screen, because you have fresh input data, and this is the closest you’ll get to Vsync.

    2. Other visual tasks, such as style calculations, are performed after this task, so it is ideally placed for mutated elements.

    3. If you mutate, say, 100 classes, this does not result in 100 style calculations; They will be processed in batches and processed later. The only thing to note is that you should not query any computed style or layout properties (such as el.style.backgroundimage or el.style.offsetwidth).

    4. If you do, you’ll bring recalculated styles, layouts, or both forward, resulting in forced synchronization of the layout, or worse, layout disruption.

  4. Parse HTML:

    1. Any newly added HTML is processed and a DOM element is created.

    2. You may see more of this during page loading or after operations such as appendChild.

  5. Recalc Styles:

    1. Styles are calculated for anything new added or mutated, which could be the entire tree or the range, depending on what’s changed.

    2. It could be the whole tree, or it could be zoomed out, depending on what’s changed.

    3. For example, changing classes on a body can be profound, but it’s worth noting that browsers have been clever enough to automatically limit the scope of style calculations.

  6. Layout:

    1. Computes geometric information (position and size of each element) for each visible element. It typically evaluates the entire document, usually making the computation cost proportional to the DOM size.

  7. Update Layer Tree:

    1. The process of creating overlay context and deep-sort elements.
  8. Paint:

    1. This is the first part of a two-part process: Drawing is a drawing call that records any new elements or visually changed elements (fill a rectangle here, write text there).
    2. The second part is rasterization (see below), where drawing calls are made and textures are filled. This part is a record of the call to draw and is usually much faster than rasterization, but these two parts are often referred to collectively as “painting.”
  9. Composite:

    1. The layer and tile information is calculated and passed back to the synthesizer thread for processing.

    2. This will take into account, among other things, things like will-change, overlapping elements, and any hardware-accelerated canvases.

  10. Raster Scheduled (Scheduled) and Rasterize (Scheduled)

    1. The draw call recorded in the Paint task is now executed. This is done in Compositor Tile Workers, the number of which depends on platform and device capability.

    2. On Android, for example, you’ll usually find one Worker, and on the desktop, you’ll sometimes find four. Rasterization is done in layers, each made up of tiles.

  11. Frame End:

    1. When tiles for each layer are rasterized, any new tiles will be submitted to the GPU thread along with the input data (which may be changed in the event handler).

  12. Frame Ships (sending frames) :

    1. Last, but by no means least, tiles are uploaded from the GPU thread to the GPU. The GPU uses quadrilaterals and matrices (all the usual GL goodies) to draw tiles onto the screen.

Basically, this is the whole process.

requestIdleCallback

To do this, we have to use the analogy of requestAnimationFrame. RequestAnimationFrame is executed before the screen is rerendered. RAF, as mentioned above, is used to optimize animation at that time, so it is good for animation.

RequestIdleCallback If you look it up by Task in the main thread, you will see that it is executed after rendering the screen, by looking at the article, usually to see if the browser is free.

Space is limited here, if you want to understand this, recommend an article:

Juejin. Cn/post / 684490…

conclusion

Recently I looked up foreign literature and found that there are too many things to learn. If this article is not written correctly, or the translation is not good, you are welcome to point out.

Welcome to the public account “TianTianUp”.

I’m TianTian and I’ll see you next time!!

reference

[1] the w3c – longTasks: github.com/w3c/longtas…

[2] the chrome – FPS – meter: developer.chrome.com/docs/devtoo…

[3] devtools – samples: googlechrome. Making. IO/devtools – sa…

[4] Analyze the runtime performance: developer.chrome.com/docs/devtoo…

[5] Timeline Event Reference: developer.chrome.com/docs/devtoo…

[6] The Anatomy of a Frame: aerotwist.com/blog/the-an…

[7] performance – rendering: developers.google.com/web/fundame…

[8] Wikipedia: zh.wikipedia.org/wiki/