directory

  • 1. Animation Caton analysis
    • The animation is stuck
    • Page rendering process
  • Second, optimization method
    • JavaScript: Optimize JavaScript execution efficiency
    • Style: Reduces style computation complexity and scope
    • Layout: Avoid large, complex layouts
    • Paint/Composite: GPU acceleration
  • Three, reference

1. Animation Caton analysis

The animation is stuck

Most devices refresh at a rate of 60 frames per second, meaning that one second of animation is generated by 60 frames linked together, requiring the browser to render each frame in 16ms. When the rendering time exceeds 16ms and less than 60 images are generated in 1 second, there will be a feeling of incoherence and stutter, which will affect the user experience.

Page rendering process

The client rendering of a page frame is divided into the following steps:

  1. JavaScript: JavaScript to achieve animation effects, DOM manipulation, etc.
  2. Style (Style calculation): Verifies the CSS style rules applied to each DOM element.
  3. Layout = Layout: Calculates the final size and position of each DOM element on the screen. Because the layout of DOM elements is relative, when one element changes and affects the layout, other elements change as well, and you need to fall back and re-render, a process called reflow.
  4. Paint.: Draws text, colors, images, borders, shadows, and so on for DOM elements on multiple layers.
  5. Composite (Render Layer merge): Merge layers in a reasonable order and display them on the screen.

When the browser actually renders the page, it needs to go through a series of mappings from the DOM tree constructed from the HTML page to the final layer. The mapping process is shown below (source:Reference [3]RenderObject->LayoutObject, RenderLayer->PaintLayer

  • Node->RenderObject: Each Node in the DOM tree has a corresponding RenderObject (one-to-one relationship, the RenderObject contains the contents of the Node);
  • RenderObject -> RenderLayer: One or more RenderObjects correspond to one RenderLayer (many-to-one). RenderLayer is used to ensure the hierarchical relationship between elements. Generally speaking, elements of the same level in the same location are located in the same RenderLayer. Only some special RenderObjects create a new rendering layer; other RenderObjects share one with the first ancestor element that owns the RenderLayer. A common RenderObject that generates RenderLayer has one of the following characteristicsReference [3]:
    • Page root element
    • CSS positioning attributes (relative, Absolute, Fixed, sticky)
    • Transparent not to 1
    • The overflow is not visible
    • The CSS mask property is available
    • CSS box-reflect property
    • The CSS filter attribute is available
    • 3D or hardware-accelerated 2D Canvas elements
    • Video elements
  • RenderLayer -> GraphicsLayer: One or more renderlayers correspond to a GraphicsLayer (many-to-one). Renderlayers that are considered to be Compositing layers correspond to a GraphicsLayer alone. The other RenderLayer shares a GraphicsLayer with the first ancestor element that has a GraphicsLayer. Each GraphicsLayer has a GraphicsContext to draw its corresponding RenderLayers, and the synthesizer synthesizes the bitmap of GraphicsContexts to be displayed on the screen. The rendering layer is promoted to the compositing layer for the following reasons:
    • Has the 3D Transform property
    • Have the perspective properties
    • 3D Canvas or hardware-accelerated 2D Canvas
    • Hardware-accelerated IFrame elements (e.g. pages where iframe is embedded have composition layers that require hardware acceleration)
    • Hardware-accelerated plug-ins, such as Flash, are used
    • Animation /transition is applied to opacity/transform property (when animation/transition is active)
    • The child element is the Compositing Layer
    • Sibling elements are the Compositing layer, which overlaps with the current non-composting layer and is hierarchically lower than the current layer
    • Will – change attribute

Second, optimization method

You can see a lot of optimization program summary on the Internet, the big guys are writing very well.

Talk is cheap. Show me the code.

Combined with the page rendering process, here will be combined with some test code to analyze the various optimization schemes and effects of animation:

  • JavaScript: Optimize JavaScript execution efficiency
    • requestAnimationFrameInstead ofsetTimeoutandsetInterval
    • Parallel DOM element updates are divided into small tasks
    • DOM independent time-consuming operations are placedWeb WorkersIn the
  • Style: Reduces style computation complexity and scope
    • Reduce the complexity of the style picker
    • Reduce the number of elements that need to perform style calculations
  • Layout: Avoid large, complex layouts
    • Avoid frequent layout changes
    • Replace the old layout model with flexbox layout
    • Avoid forced synchronization of layout events
  • Paint/Composite: GPU acceleration
    • Promote moving or tween elements from the RenderLayer to the Compositing Layer
    • Avoid the pitfalls of ascending layers of synthesis

JavaScript: Optimize JavaScript execution efficiency

1. requestAnimationFrameInstead ofsetTimeoutandsetInterval

Why are setTimeout and setInterval bad? Js is a single thread execution, so in order to prevent a task execution time is too long to cause process blocking, there is the concept of asynchronous queue in JS. For setTimeout and Ajax requests, the process is put into the asynchronous queue, and the task in the asynchronous queue is executed only when the main process is empty. Therefore, setTimeout and setInterval cannot guarantee the execution timing of the callback function, and may execute multiple times within a frame, resulting in multiple page rendering, wasting CPU resources and even lag, or execute at the end of a frame, resulting in re-rendering and frame loss. How is requestAnimationFrame optimized?

  • CPU saving, pauses rendering when the page is hidden or minimized.
  • Function throttling, whose loop interval is determined by the screen refresh frequency, ensures that the callback function is executed only once in each screen refresh interval.

How about the specific optimization effect?DEMO

View the performance differences on the Chrome Performance panel.

throughsetTimeoutRender 3 times and have long frames:



userequestAnimationFrameDOM manipulation was partially merged, only 2 renders were made, and long frames were optimized:

2. Time consuming operations unrelated to DOMWeb WorkerIn the

What are the benefits of Web workers? JavaScript is single-threaded, and frequent time-consuming operations (such as updating data in real time) can cause congestion and affect user interaction. The function of Web Worker is to create a multi-threaded environment for JavaScript. The Worker thread runs in the background and is controlled by the main thread without interference between the two. The worker thread takes care of high-latency, UI-unrelated tasks, and the main thread takes care of UI interactions relatively smoothly. Need to pay attention to

  • Web WorkerYou can’t manipulate the DOM, essentially separating data refresh and page rendering.
  • Web WorkerFollow the same origin policy and restrict local access.
  • Trade an extra network request and browser thread resources for efficient execution.

How about the specific optimization effect?DEMO

You can view specific performance differences on the Chrome Performance panelweb worker, reduces a network request, but there is a long time frame, there is the risk of frame jam.



Using theweb workerAfter that, tasks unrelated to time-consuming operations are no longer blocked, but network latency is increased. If you use worker in a project, the initialization time needs to be carefully considered.

Possible application scenarios

  • Polling server for data
  • Frequent data reporting
  • Time-consuming data processing

Style: Reduces style computation complexity and scope

1. Reduce the complexity of the style picker?

Reducing the complexity of style selectors is a frequently proposed optimization method. In fact, the effect of this method is weak. According to Ivan Curic’s test method (DEMO) in article [5], in a page with 50000 nodes, the effect of different selector complexity on performance is not more than 20ms, and in general, None of the pages will have this number of nodes. The reason for the weak optimization effect is that the browser engine optimizes the speed of the selector, and different engines have different performance optimizations, so it is hard to predict whether the developer’s optimization is effective, at least for static elements, the optimization cost is extremely low. One thing the tests confirmed was that the use of pseudo-class selectors and overly long selectors should be reduced. It is recommended to organize CSS according to naming conventions such as OOCSS and BEM. The advantage is that it improves code maintainability while slightly optimizing performance.

2. Reduce the number of elements that need to perform style calculations

This is for older browsers, where changing a class on the body element requires recalculating all of its children. Modern browsers are optimized, so the optimization effect depends on the application scenario. At present, no application examples have been excavated, and the pit will be filled if any discoveries are found later.

Layout: Avoid large, complex layouts

1. Avoid triggering layouts too often

Different attributes result in different rendering costs, and this is especially true when it comes to CSS animations. The animation properties that trigger Layout or Paint are particularly performance-intensive and should be used whenever possibletransformandopacityAs an animation property, consider implementing animations in JavaScript if this is not possible.

How different is the performance?Taking Width and Transform as examples, the performance differences of animation are realized respectively:DEMO

< span style = “box-sizing: border-box; color: RGB (51, 51, 51); line-height: 16px; font-size: 16px! Important; word-break: break-all;”



Animate by Transform, you can see that the frame rate is also low but smooth, and the rendering process only triggers the style calculation and the merge of the, draw and render layers (only if the element is a composite layer, no drawing is triggered. More on this later) :

2. Replace the old layout model with flexbox layout

Classic layouts such as floating-based layouts and absolute positioning layouts are more efficient than flexbox layouts. In projects where flexbox layout is possible, use Flexbox layout as much as possible. The followingDEMOTry rendering the same interface with three layouts to test performance:

Absolute layout: Unique positioning coordinates are required for each element. When there are many elements, CSS files tend to be larger, resulting in more time spent on style calculations.



Floating layout: The positioning of floating elements is influenced by each other, and some floating elements are also influenced by document flow, resulting in a longer layout time.



Flexible layout: Compared with the previous two layout schemes, the performance is significantly improved.

3. Avoid forcible synchronization of layout events

What is forced synchronous layout?

The page rendering process is JavaScript->Style->Layout->Paint->Composite. Forcing a synchronous Layout forces the browser to execute the Layout before executing the JavaScript script.

What would cause forced synchronization of layouts?

When JavaScript is running, the element attribute styles obtained are the values of the previous frame, so if you modify an element attribute of the current frame before retrieving it during the rendering process of the current frame, the browser must apply the attribute before executing the JavaScript logic. In short, DOM write before read operation. In particular, continuous read and write operations have a greater impact on browser performance.What is the performance impact?DEMO

DEMO tests the impact of forced synchronization layout events on performance by changing the properties of 1000 nodes. For details, see the following figure. It can be found that the performance loss is very large, continuous read and write operations cause continuous forced synchronization events to be fired, and JavaScript execution time becomes very long:

Paint/Composite: GPU acceleration

1. Promote moving or tween elements from RenderLayer to Compositing Layer

Note: The Layers can be viewed in the Layers panel of Chrome’s Developer Tools. Open the Layers panel using Command + Shift + P (MAC)/ CTRL + Shift + P (Windows) -> show layers to promote complex/frequently changing elements to the layers layer. The advantage of this is that the drawing of this element does not trigger the drawing of other elements. The render layer is promoted to the composition layer for the following reasons (note that the following reasons are based on the render layer) :

  • Has the 3D Transform property
  • Have the perspective properties
  • 3D Canvas or hardware-accelerated 2D Canvas
  • Hardware-accelerated IFrame elements (e.g. pages where iframe is embedded have composition layers that require hardware acceleration)
  • Hardware-accelerated plug-ins such as Flash/IFrame are used
  • Animation /transition is applied to opacity/transform property (when animation/transition is active)
  • The will-change properties are opacity, transform, top, left, bottom, and right
  • The child element is the Compositing Layer
  • Sibling elements are the Compositing layer, which overlaps with the current non-composting layer, which is lower than the non-Composting layer

Why the performance boost?

  • Only redraw what needs to be redrawn
  • GPU acceleration: Bitmaps of the synthesis layer are synthesized directly by the GPU, which is faster than CPU processing

How much performance improvement? DEMOAs you can see in the demo, the time required for paint is greatly reduced after the promotion to the composition layer.

Is it possible to ascend as many layers as possible?

As you can see, paint time drops dramatically when you raise the composition layer. However, the creation of the composition layer consumes additional memory and management resources, and excessive composition layers bring a large memory overhead to the page.DEMO5000 elements were created, all of which were promoted to the composition layer compared to memory consumption without promotion. This is especially important on mobile devices, where memory resources are more constrained than on PCS.

Based on the principle of enhancing the rendering layer of only animation elements to the composition layer to improve performance, when the drawing of other parts of the page is complicated and relatively static, we can consider promoting animation elements to the composition layer separately to reduce the influence of animation elements on other elements of the page.

2. Avoid the pitfalls of ascending compositing layers

To review the last reason for the promotion to the composition layer: Sibling elements are the Compositing layer, which overlaps with the current non-composting layer, which has a lower level than the non-Composting layer.

The resulting layers of ascension synthesis are generally not expected. The reason is related to the rendering process of the screen. Recall the last step of the page mapping, where each Compositing Layer corresponds to a bitmap, and the synthesizer finally combines these bitmaps according to the hierarchy and outputs them to the screen. At this point, we assume that A is the known composition layer, and B ideally should be the ordinary rendering layer, with the hierarchical relationship as shown in the figure:



As A common rendering layer, B and its parent element are in the same bitmap, and A is in A bitmap alone. In this case, there will be problems with the hierarchy when merging. If B is directly placed above A, it may cause the parent element of B, whose level is lower than A, to be displayed above A instead. The browser’s solution at this time was to render B as a Compositing layer separately, resulting in the unexpected generation of the Compositing layer. Wouldn’t the first instinct at this point be to avoid overlap? But things are not simple. In the search for information found a pokemon –assumedOverlap. The browser assumes overlap for elements that cannot/cannot determine whether they will overlap with the Compositing layer and elevates them to the Compositing layer.

The browser has also been optimized to merge successive rendering layers that overlap with compositing layers into one compositing Layer through Layer Squashing. Prevent too many lifting composite layers caused by overlap, resulting in Layer Explosion, please refer toDEMO.

However, there are still problems with layer compression, checkThe source codeList the following reasons (note that they are all overlapped/assumed overlaps) :

  • scrollsWithRespectToSquashingLayerThe render layer is rolled relative to the compression layer. When the rolled render layer overlaps with the compositing layer, a new compositing layer is created and cannot be compressed.DEMO(this example is not very good, codepen embedded with iframe, the entire IFrame becomes the composition layer, if you want to see the effect can be viewed locally)
  • squashingSparsityExceededThe render layer compression causes the compression layer to be too sparse.DEMO
  • squashingClippingContainerMismatchThe render layer and the clipping container of the compression layer are different. Simply understand, the container overflow type of the overlapping render layer is different.DEMO
  • squashingOpacityAncestorMismatch: The rendering layer is different from the opacity attribute inherited from the ancestor of the compression layer.DEMO
  • squashingTransformAncestorMismatchThe render layer is different from the ancestor transform of the compression layer.DEMO
  • squashingFilterAncestorMismatch: The render layer is different from the filter attribute inherited from the ancestors of the compression layer, or the render layer itself has the filter attribute.DEMO
  • squashingWouldBreakPaintOrder: cannot compress without disrupting the rendering order (e.g. parent element has mask/filter attribute, child element and compression layer overlap, if merged, the mask/filter attribute of parent element cannot be partially applied in compression layer, resulting in errors in rendering results).DEMO
  • squashingVideoIsDisallowedThe: video element cannot be compressed.DEMO
  • squashedLayerClipsCompositingDescendantsWhen the compositing layer is a clipped child, the overlapping render layer cannot be compressed.DEMO
  • squashingLayoutPartIsDisallowed: Cannot compress the frame/iframe/plugin.
  • squashingReflectionDisallowed: cannot compress the rendering layer with reflection property.DEMO
  • squashingBlendingDisallowed: cannot compress layers with the Blend mode attribute.DEMO
  • squashingNearestFixedPositionMismatchThe render layer’s most recent fixed element cannot be compressed, unlike the compression layer.DEMO

When you find that there is no content on the page, but you can check whether this is the reason, the following gives common layer compression can not solve the situation:

  1. withtransformThe element of the animation, and the element following itrelative/absolutepositioning

The reason: Relative element and absolute element under relative are promoted to composition layer due to assumedOverlap, and overflow:hidden is set, Based on the aforementioned squashingClippingContainerMismatch, rendering layer and synthetic cutting container is different, lead to can’t layer compression, appear too many composite layer. Setting z-index to the elements of the animation disturbs sorting of the Compositing layer. DEMO

Three,reference

The structure of this paper mainly refers to article [1], some of the optimization points of the actual test and expansion, also can be regarded as a reading of it ~ about layer compression part of the situation is too complicated, did not find what information, feel not fully understood, there is a chance to rearrange it. Thanks to the following big guy!

  1. How much do you know about browser rendering performance? www.jianshu.com/p/a32b890c2…
  2. Optimizing CSS: ID Selectors and Other Myths www.sitepoint.com/optimizing-…
  3. GPU Accelerated Compositing in Chrome www.chromium.org/developers/…
  4. IO /notes/2017/…
  5. Blink Compositing Update: Recap and Squashing docs.google.com/presentatio…
  6. Wireless performance optimization, the Composite taobaofed.org/blog/2016/0…

The end of flower sprinkling welcome advice

AD time

Feizhu is bytedance’s office suite product, which deeply integrates functions such as instant communication, online collaboration, audio and video conferencing, calendar, cloud disk and workbench to provide users with one-stop collaboration experience. At present, feishu service customers have covered science and technology, Internet, information technology, manufacturing, construction and real estate, enterprise services, education, media and other fields. Welcome to the bytedance flying book team, there are a large number of front-end and back-end HC ~ scan the TWO-DIMENSIONAL code or click the link to send, look for the flying book team 👍 ~

Internal push code: HZNVPHS, delivery link:job.toutiao.com/s/JaeUCoc

[Recruitment] Delivery link:job.toutiao.com/s/JaevUNo