2.9.16
Coherent GT
A modern user interface library for games
Appending and removing elements

Some tips and techniques on how to minimize the performance impact when appending children using .appendChild. Appending many children all at once may cause longer frames, but by using .requestAnimationFrame this can be avoided. There is no predefined number of how many elements can be appended at once - profiling is highly recommended for each case in each scene.

Factors:

  • How many elements will be appended?
  • How many nested elements the appended element has?
  • What styles are applied - box shadows, filters, transforms?
  • Is the UI running in-game or not?

Appending children without .requestAnimationFrame:

Visually this may be the fastest way to create and show elements on the scene but this does not come without a cost. Creating many elements at once can cause frame bottleneck which is not a desired effect. If those elements have box shadows or any filters, the frame will be prolonged. Also when too many elements are created with images which load for the first time in the scene, those images will visualize at the end of the frame. For some images you may even consider preloading them in advance (Loading UI textures in advance (preload textures)).

In this example 20 elements are requested to be appended in one call. Each of them contains 21 more elements inside. This brings a total of 440 elements.

20_no_raf.png

You can see from the Timeline that this operation takes more than 4 milliseconds.

Appending children with rAF:

This is the lightest way to create and append children with minimal performance impact. It doesn't matter how many elements should be created. Basically the window.requestAnimationFrame method is responsible for calling a function before the next Paint. The downside is that if many elements are requested to be appended with rAF, their visualization on the screen may be noticeable. To counter this effect, more than one element can be requested to be appended on a single call.

Same 20 elements are appended, but each one is created separately.

20_raf.png

Frame-by-frame this is the lightest way when creating and displaying elements on the screen.

Appending children with rAF on chunks

Depending on the case, this technique can entirely remove the noticeable effect when creating a list of elements with rAF. The number of elements created at each .requestAnimationFrame should be adapted according to the weight of the scene.

In this example rAF is used, but instead of creating 1 element on each request, 3 are created.

20_raf_chunks.png

You can see that the time taken to append and visualize the created elements on the screen is shorter than if appended one by one on each call.

Summary - appending children

The lightest and recommended way to create and append children is to split the workload over several frames using .requestAnimationFrame. Appending them in one call can lead to unnecessary and unwanted prolonged frame.

Note
When creating elements, always remember to change/update the content inside that element before appending it. The order should be: create -> update -> append. If the order is create -> append -> update there can be unnecessary Layouts, Paints and recalculating of styles.

Removing elements (no rAF)

This section of the guide about removing elements emphasizes on the case where many elements are removed. Removing elements is a much lighter process than creating them.

Removing many children at once is doing less work than when using .requestAnimationFrame for each element. One or a few times there is a need for a Layout and Paints, depending if the elements are removed in a single call or on portions using rAF.

Single call example with the same 440 element.

remove-children.png

Removing elements with .removeChild (rAF)

As opposed to appending elements with .requestAnimationFrame, removing them this way is heavier. Creating and visualizing an element on the screen is always heavier than removing it. So each time an element is removed from the list, an update to the Layout is needed. Paint is also done each time although if these elements are layers, the Paint is minimal (layers will be discussed later in this guide).

Removing elements with rAF on chunks

This is the middle ground. In extreme case - if many elements need to be removed, they can be removed on portions using rAF. Lets say 50 elements need to be removed, but removing them at once can lead to a longer frame. Removing them by 5 or 10 will distribute the load in separate frames.

Summary - removing children

It is perfectly acceptable to remove children in one go. The catch is if too many elements need to be removed, partitioning the removal on portions will be better. "Too many" is defined by the weight of the scene. Profiling is the key to define the correct number.

Note
Do not empty a list of elements with container.innerHTML = "", with .textContent or with Node.innerText. Although they do the job, this is not the proper way to remove children and these methods won't gain any performance. This is not their intended purpose.