What’s in this article: Why we’re aiming for 60 frames per second, what’s involved in the browser rendering of each frame, and why different properties of CSS affect performance in different ways. How the browser spends time per frame. How to use the browser to find performance bottlenecks.

APP life cycle (RAIL)

We call the application life cycle four areas: Response, Animate, Idle, load, or RAIL.

Initial load should be in 1 seconds, when loading is completed, usually idle, waiting for the user action, this time the browser is dealing with in order to satisfy the 1 s work was delayed finished loading your goal, usually the idle time of about 50 ms, while idle time may appear more than once, the idle time is an excellent chance to complete complex tasks. So that everything is smooth and fast when the user interacts.

So what is the level of responsiveness? Studies show that there is an upper limit of 100ms, when the user presses something on the screen it is even more challenging to animate it and it needs to be 60fps, 1000ms/60=16ms. In fact, since the browser also needs processing time, it only takes 10-12ms.

Key render path

Most devices now refresh their screens at a rate of 60 frames per second, and if the browser takes too long to display a frame, a frame is lost, frame speed slows, and the user sees a stutter. If things get really bad, the whole screen freezes.

You can’t optimize your app’s frame rate if you don’t know how the browser renders frames, so you need to understand how the web page appears on the screen when it’s loaded, and I’ll walk you through this process.

Build a DOM tree

First, the browser sends a fetch request to the server, and the server responds with HTML. At this point, the browser takes very intelligent measures and parses in advance to generate a DOM tree.

Calculate the style

Generate the CSSOM tree from THE CSS and calculate the style of each element.

Calculate the layout

Computing geometric information for each node in the DOM tree, that is, calculating the space taken up by each element, where on the screen

Dom combines CSS to obtain a new tree, called a rendering tree, also known as a layout tree.

If the CSS sets display: None, it will be removed from the rendering tree.

draw

Perform rendering

Composition and display

And when it’s done, it looks like this

The contents of a single frame

Typically a single frame contains the following

How does CSS affect the content of frames

Rearrangement: Updates the geometry of an element. Such as the width and height of the element, the browser triggers a relayout and a series of sub-stages after parsing. Of course, reordering requires updating the entire rendering pipeline, so it’s also the most expensive.

Redraw: Updates the draw attribute of an element. For example, the background color is omitted, and the frame looks like this:

Direct compositing phase: Animate using CSS’s Transform, which avoids rearranging and redrawing and executes compositing directly on a non-main thread. This is the most efficient, because it is synthesized on a non-main thread and does not consume resources on the main thread. The final frame looks like this:

So different styles affect frame generation, which in turn affects performance.

View single frame content

In developer tools, how the browser spends time per frame.

Go to developer tools-Performance and click Record. The browser collects page information and generates two views.

5. flame chart

The icon extends down from the top, and if some part of the pipe triggers something else, the child record is displayed below the parent record.

If you zoom in on this section, you can see that the animation frame is triggered and other javascript is called, causing calc style and causing layout. You can see which events led to which events.

The waterfall view

You can see what the action was, how long it was, when it started, then break it down a little bit, the time itself and any sub-records, and finally see where in the code the task was triggered.

Recalculate style shows the number of elements affected.

Layout shows the size of the tree, the range, the starting position, and where the code triggers the layout.

Identify problematic code and analyze performance bottlenecks

Case 1: Click on me

The site’s record looks pretty close to 60 frames per second. But not entirely, all purple bars indicate that too many layout events may have occurred. When zoomed in, it became clear that there were problems with these layouts.

warning:Force synchronous layout is a possible persormance bottleneck

Line 172 from the script quiet, the culprit. Click to see the functions that cause the forced layout.

Open to see, each frame is caused by the function onSwitchLayoutClick call. Modifies the element class, which modifies the width of the element, causing a rearrangement that triggers a browser relayout.

Case two: Point at me

We see a lot of green bars in the timeline, obviously there are drawing problems, zoom in on one frame and see

It looks like every Frame starts with a script and has an Animation Frame Fired event followed by a style calculation and draw event, which seems to be a JavaScript problem, because if the problem comes from CSS, you won’t see the Animation Frame Fired event.

RequestAnimationFrame

The time limit for animation is 16ms, which is actually only about 10ms to perform all the operations and get the frames ready including running layout, composition and drawing.

RequestAnimationFrame is an API that allows your JavaScript to run at the appropriate time of each frame. RequestAnimationFrame should be a must when you create animations. To reach 60fps the browser has no render time at all, there is some extra work to be done in the browser while rendering each frame, so we should keep the render under 10ms.

The JavaScript portion of a frame should generally be kept at a maximum of 3 to 4 milliseconds, as there is more work to be done afterwards, such as style calculations, layer management and render layer merging.

Let’s say there’s some styling work, and then there’s JavaScript to work with, and the browser needs to work with the inserted JavaScript before moving on to other tasks, and the new JavaScript might cause the frame to work backwards. I might have lost this frame.

So execute as early as possible at the beginning of each frame. This gives the browser as much time as possible to run the code.

Much of the older code on the web for animation uses setTimeout.

The problem with these two functions is that the JavaScript engine doesn’t care about the rendering pipeline at all. They come in handy if you want to wait for a while or repeat some tasks frequently, but they are not suitable for animation.

RequestAnimationFrame usage

Call it, tell it which function to call, and schedule the next animation at the end of the RequestAnimationFrame. The browser knows when to run and how to run. Internet explorer does not support

Forcibly synchronize layout FSL

Am I

If you trigger forced sync layout, you will see a red triangle in the upper right corner of the layout record in frame view.

Find the problem code:

The browser must calculate offsetWidth, which requires the layout. Every time you change the style, the layout process that you just performed becomes invalid because you changed the style and now the browser has to do it all over again, and the error code is very high.

The layout runs ahead of the computed style

Click me to see which CSS triggers the layout.

Avoid FSL

Reading the layout properties first in the JavaScript phase means that you will use the layout of the previous frame and then make all the style changes.

Check out the how-not-to-trigger-layout-in-WebKit yourself

Impact of CSS selectors on performance

Am I

It turns out that Recalculate Style’s self time is too long to reach 60 frames/SEC.

Complex CSS selectors like nth-Child can add a lot of work to the browser when pages have a large number of elements. The more complex the selector, the more times the browser has to move up and down the DOM tree, and the more times it moves, the longer it takes to find the right element.

Solutions:

– Reduce affected elements

– Reduces selector complexity

Bem is the block element modifier. It uses the name of a single class for style elements. And it’s better for performance. Because class matching is usually the fastest selector for modern browsers.

Block

Element

Modifier

For example: box – three

More on block element modifiers:

bem-smacss-advice-from-developers

key-concepts