I recently wrote a post on how to optimize Amap animation using Chrome DevTools, which mentioned composite but didn’t go into detail. After thinking for a long time, I still feel the need to summarize.

What is composite?

In plain English: Each node in the DOM tree corresponds to a LayoutObject. When their LayoutObject is in the same coordinate space, a RenderLayers will be formed, that is, the rendering layer. RenderLayers ensure that the page elements are composited in the correct order, resulting in a composite that handles the display of transparent and overlapping elements correctly.

Once the page is loaded and parsed, it is represented in the browser as a structure familiar to many Web developers: the DOM. However, when rendering a page, the browser has a series of intermediate representations that are not directly exposed to the developer. The most important of these structures are layers.

At this point, the idea of a layer is there. Composite translates to “composite”, so how does it work?

RenderLayers and GraphicsLayers

Post a flow chart and we’ll talk about it later:



There are several different layer types in Chrome:

  • The RenderLayers render layer, which is responsible for corresponding DOM subtrees
  • GraphicsLayers graphics layer, which is responsible for the RenderLayers subtree.

RenderObjects: RenderLayers: RenderObjects preserves the tree structure. A RenderObjects knows how to draw the contents of a Node by making the necessary draw calls to a GraphicsContext.

Each GraphicsLayer has a GraphicsContext. The GraphicsContext is responsible for the output of bitmaps of this layer. Bitmaps are stored in shared memory and uploaded to GPU as textures. Then draw to the screen, at which point our page is displayed on the screen.

The GraphicsContext is responsible for drawing pixels to the screen (the process of writing pixel-level data to a bitmap before displaying it on the display). In Chrome, the GraphicsContext is wrapped in Skia (Chrome’s own 2D graphics drawing library).


3. Implicit composite

For implicit composition, CSS GPU Animation describes it as follows:

This is called implicit compositing: One or more non-composited elements that should appear above a composited one in the stacking order are promoted to Composite layers — i.e. painted to separate images that are then sent to the GPU.


Let’s take a look at the following illustration:

Suppose A scene, we need A to be displayed on B, and then add moving animation for B, there will be A logical problem: B is promoted to the synthesis layer because of animation, and the screen image is finally synthesized on GPU, while A needs to be displayed on B, we do not do any processing. So in order for A and B to display properly, we need to set z-Index, and the browser will force A to be promoted to the composite layer, followed by repaint.

At this point, composite implicit composition appears. Of course, there are more scenarios, so let’s move on.

4. Factors affecting composite

We know that under certain conditions, the browser will actively push the render layer to the composite layer, so what factors affect the composite?

  1. Transforms: Translate3D, translateZ etc.
  2. Video, Canvas, iframe and other elements;
  3. Animation-opacity conversion via element.animate ();
  4. Opacity animation conversion via с SS animation;
  5. position: fixed;
  6. will-change;
  7. filter;
  8. There are offspring of synthetic layer and overflow is not visible (if SelfPaintingLayer is generated by explicit positioning factor, z-index should not be auto) etc…

Here are just a few examples, wireless performance optimization: Composite, which is described in great detail and will not be covered here.

Five, layer compression and layer explosion

1. Layer compression: Similar to the example of implicit layer composition, simple overlapping may result in a large number of composite layers, which will consume a lot of innocent CPU and memory resources, and seriously affect the performance of the page. The browser takes this into account, so Layer Squashing comes into play.

Automatic layer compression in browsers is also not a panacea, and there are many specific situations where it is impossible for browsers to layer compress.


  • Unable to perform compression that would break the render order
  • The render layer of the video element cannot be compressed and other render layers cannot be compressed onto the compositing layer where the video is located
  • The iframe/Plugin rendering layer cannot be compressed and other rendering layers cannot be compressed into the compositing layer
  • Unable to compress a reflection properties of rendering layer (squashingReflectionDisallowed)
  • Unable to compress a blend mode attribute of the render layer (squashingBlendingDisallowed)
  • When rendering with composite layer with different cutting container (clipping container), unable to compress the render layer (squashingClippingContainerMismatch)
  • Relative to the synthesis of rolling rendering layer cannot be compressed (scrollsWithRespectToSquashingLayer)
  • When rendering layer with synthetic have different opacity of the ancestral planes (a set the opacity and less than 1, a not set opacity, is different), unable to compress the render layer (squashingOpacityAncestorMismatch, With squashingClippingContainerMismatch)
  • When rendering with synthetic layers have different with the transform of the ancestral planes, unable to compress the render layer (squashingTransformAncestorMismatch, ditto)
  • When rendering layer with synthetic have different with the ancestors of the filter layer, unable to compress the render layer (squashingFilterAncestorMismatch, ditto)
  • When the cover layer synthetic running animation, unable to compress the render layer (squashingLayerIsAnimating), when the movie did not start or run is completed, the render layer can be compressed

Wireless performance optimization: Composite

If multiple render layers overlap with a composite layer, they are compressed into a Single GraphicsLayer to prevent possible “layer explosions” due to overlapping.

2. Layer explosion: From the previous introduction, we know that overlapping compositing layers also causes elements to be promoted to compositing layers. Despite the browser’s layer compression mechanism, there are many cases where compression is not possible. In other words, in addition to the explicitly declared composite layers, some unexpected composite layers may be inadvertently generated due to overlapping reasons, and a large number of additional composite layers may be generated at the extreme, resulting in the phenomenon of layer explosion.

To solve the problem of layer explosion, the best solution is to break the condition of overlap, that is to say, let other elements not overlap with elements of composite layer, such as clever use of z-index attribute.

Six, memory consumption

As mentioned above, the process of layer composition will generate memory consumption, so how do we evaluate the memory consumption of layer composition? Here is an example to illustrate:

<! -- jartto test --> <div id="a"></div> <div id="b"></div>Copy the code

#a, #b {
 will-change: transform;
}
#a {
 width: 100px;
 height: 100px;
 background: rgb(255, 0, 0);
}
#b {
 width: 10px;
 height: 10px;
 background: rgb(255, 0, 0);
 transform: scale(10);
}Copy the code

As shown above, we created two containers # A and #b, where # A has a physical size of 100×100px (100×100×3 = 30000 bytes) and # B is only 10×10px (10×10×3 = 300 bytes) but is magnified by 10 times. #b The transform animation will render the layer using the GPU due to the will-change property.

We get the number of pixels in the image by multiplying the height of the image by the width of the image. We then multiply this by 3, because each pixel is described in three bytes (RGB). Then it is not difficult to understand that if the image contains a transparent region, we multiply by 4, as additional bytes are required to describe transparency: (RGBA) : 100×100×4 = 40000 bytes.

From the above example, we draw a very interesting conclusion that helps us to do some simple optimizations. For example, if you want to animate a large image, you can download a smaller version (10% of the original) and zoom in. This is unconscious to the user, but we have streamlined the page load to improve the user experience.

Whereas, Reflowing and Repainting

Good, we can use the above to evaluate the memory consumption, which leads to the terms Reflow and Repaint, just to review:

  • Reflow: The browser takes time to render, and when it finds that something has changed that affects the layout, it needs to go back and re-render.
  • Repaint: Changing an element’s background color, text color, etc., will only cause the browser to Repaint a part of the element without affecting the surrounding or internal layout of the element.

Reflow takes more time than Repaint, which affects performance more. So when writing code, try to avoid too many reflows.

Reflow reasons:

  • When the page is initialized;
  • When manipulating DOM;
  • The size of some elements has changed.
  • If the properties of the CSS change.

Reduce reflow/repaint

  • Don’t change the STYLE of the DOM line by line. Instead, define the CSS class in advance and change the DOM className.
  • Do not place DOM node property values in a loop as variables in the loop.
  • Use fixed or Absoult position for animated HTML elements, then modifying their CSS will not reflow.
  • Never use a table layout. Because a small change can cause the entire table to be rearranged.

Hardware acceleration

Since the entire rendering process is so time-consuming, it’s easy to understand why most people prefer to use translateZ(0) with will-change to turn on hardware acceleration.

This brings us back to the focus of this article: the synthesis layer. The best way to improve the composition layer is to use the WILL-change property of CSS. Setting will-change to opacity, transform, top, left, bottom, and right elevates an element to a composite layer.

Let’s take a look at will-change’s browser supportClick to view



Overall support is good, so we can use it like this:

#jartto {
  will-change: transform;
}Copy the code

Of course, for some browsers that don’t support translateZ(0),Click to view



#jartto {
  transform: translateZ(0);
}Copy the code

We already know that animation of transform and opacity via CSS transitions or animations automatically creates a compositing layer and works on the GPU.

So the question is, hardware acceleration depends on the GPU, and why is the GPU faster than the CPU? Let’s see.

CPU (Central processing Unit) and GPU (Graphics Processing unit)

As CPU and GPU are mentioned repeatedly in this article, many children may wonder why hardware acceleration is enabled and what is the advantage of GPU?

Let’s first briefly understand the working principle of GPU. The process of GPU processing data is like this:

  • Draw each composite layer into a separate image;
  • Prepare layer data (size, offset, transparency, etc.);
  • Prepare animation shaders (if applicable);
  • Send data to GPU;

As you can see from the pu-Accelerated – Compositing-in-Chrome article, there are three benefits to hardware compositing:

  1. Compositing layers on a GPU can be more efficient than a CPU (both in terms of speed and power consumption) in drawing and compositing operations involving large numbers of pixels. Hardware is designed for these types of workloads.
  2. Content on the GPU does not require expensive read-back (e.g. accelerated video Canvas2D or WebGL).
  3. Parallelism between CPU and GPU, which can be run simultaneously to create efficient graphics pipelines.

The images that make up the cache elements are faster, and this is the strength of the GPU: it can quickly compose images with sub-pixel precision, which adds significant smoothness to the animation.

To put it this way, a GPU is a separate computer: an important part of every modern device is actually a separate unit, with its own processor and its own memory and data processing model. Like any other application or game, the browser must talk to the GPU like an external device.

For more on gpus, see portal here, but I won’t go too far here.

X. Supplementary: Respective responsibilities of CPU and GPU

Let me add one more thing here:

We can say that everything the CPU does is at the software level, whereas the GPU is at the hardware level, and we can do everything with software (using the CPU), but for image processing, it’s usually faster to do it with hardware because the GPU is optimized for highly parallel floating-point computing using images.

This is one of the things I’ve been frustrated with before, the emphasis on hardware acceleration rather than the CPU itself. The general process may be as follows:

  1. The CPU calculates the display and submits it to the GPU
  2. Put the rendering result into the frame buffer after GPU rendering is completed
  3. The video controller reads the frame buffer line by line according to the VSync signal and passes the data to the display through possible digital-to-analog conversion

We’ve seen that gpus are really powerful, but it’s probably best not to throw everything at gpus. The problem is that Gpus don’t have unlimited processing performance, and once they run out of resources, performance starts to decline (even if the CPU isn’t fully occupied). As a matter of fact, they have their own duties, each performing their own duties and exerting their talents, so as to play a greater role.

11. Tool use

We do not fight unprepared battle, reasonable use of tools, can greatly improve the efficiency of programming. Here is an article to optimize amap animation, including:

  • Page performance detection
  • Chrome Animation Debugger (Animations)
  • Page Rendering (Rendering)
  • Layers
  • GPU and composite layer

Forgive me for the titletag, but what started out as a way to optimize amap animation ended up as a practical example, step-by-step introduction to Chrome DevTools. The article has been published, so I am not changing the title. If possible, I would like the title to be: Animation optimization how to use Chrome DevTools

12. Optimization suggestions

Ascension to the composite layer has the following benefits in brief:

  • The bitmap of the composite layer will be synthesized by the GPU faster than the CPU
  • When repaint is required, only repaint itself is required and no other layers are affected
  • Transform and opacity do not trigger paint after an element is promoted to a composition layer, or if it is not a composition layer, it still does.

If you’ve put an element into a new compositing layer, you can use Timeline to see if doing so really improves rendering performance. Do not blindly improve the composite layer, be sure to analyze its actual performance.

In fact, on devices with limited memory resources, the performance gains from the composition layer may not be matched by the negative impact of excessive composition layer overhead on page performance. Also, since the textures of each rendering layer need to be uploaded to the GPU for processing, we also need to consider the bandwidth between the CPU and GPU, and how much memory is available for the GPU to process these textures.

So, you can see why we use method two instead of method one:

/* @frames move {from {left: 30px; } to { left: 100px; }}Copy the code

/* @keyframes move {from {transform: translateX(0); } to { transform: translateX(70px); }}Copy the code

Xiii. Conclusion

Optimization is actually a process, we need to deal with point by point, breakthrough. Nothing happens overnight, and there is no silver bullet. As high school physics books say about errors: “Errors are inevitable and can only be reduced.”

Optimization is the same, we can only do it, not force it. Try again, and you will never die.

Reference: Wireless performance optimization: Composite CSS GPU Animation Web optimization GPU-accelerated – Compositing-in-Chrome view rendering, CPU and GPU lag causes and optimization solutions