This is the 9th day of my participation in Gwen Challenge
preface
Said in yesterday’s article, on the basis of the egret engine H5 game scene management, the basic approach is to create a scene management classes, but many engine framework does not involve UI management, HTML 5 network game and web game, belongs to open the browser can directly play, some of them are mobile terminal (mobile phone or tablet), However, we should not load all the UI resources when entering the game, and if we reload and release each time we switch scenes, the game experience will be affected. Therefore, for a large mobile game with rich UI resources, scene switching and UI resources must be reasonably managed to deeply optimize game performance and reduce draw All and memory consumption.
Reading outline:
- 1. Game scene management
- 2. Game UI resource management
- 3. Introduction to GC mechanism
Game scene Management
In the same way as the above, first create a parent class of all scenes Scene, create a Scene manager SceneManger, all scenes switch, pop up and close are controlled by SceneManger class, so as to facilitate unified management of scenes.
abstract class Scene extends eui.Component{
public constructor() {
super(a);// After the listener component is created, the appearance of the scene is created
this.addEventListener(eui.UIEvent.CREATION_COMPLETE,this.onComplete,this);
}
protected abstract onComplete();
}
Copy the code
Remember to introduce the SceneManage management class in the entry file main.ts, first delete the code in the createGameScene() method in main.ts, then call the following method to make this the starting scene (stage). Without further elaboration, UI panel management is introduced below.
Game UI Management
Why manage UI resources for different scenarios, instead of loading and destroying a shuttle?
Of course not. For example, if there is a function, now there is a game project, the player enters the world scene, and then switches from the world scene to enter the scene of my home, how to design? Of course, it is also possible to access the replica map and so on. How do you do that?
There must be basic functions for entering a scene, exiting a scene, re-entering a scene, exiting a scene, cleaning up a scene, and updating a scene. Most games are basically like this. When you have a scene, you need to manually create a manager, otherwise every time you switch scenes, the UI will be completely clean. Some people say that even if the object pool is not cleaned up, the interface resources should be freed, which is not reasonable, because you cannot guarantee the reuse of the scene.
It is more conservative, pipe, UI to the UI scene to scene, scene switch management class, the UI should also need to do an LRU strategy, in this case, the UI need to clean up, according to using frequency has not to for 15 minutes at a time, for example, we can don’t think the UI resources use frequently, so we can get atlas and memory, Here only need to set a timer, each time you open the record on time, and I only for closed panel traversal, because already open the panel don’t need to clean up, also do not need to test, the UI resources in the most or atlas of memory, if can remove low frequency use of atlas can save a lot of memory, reducing the overall memory pressure, Also, large game UI resources are the largest in terms of game volume.
The default underlying operation of the game engine we normally use is to automatically clean up the UI as soon as it is closed, which causes the CPU to heat up, and while this actively cleans up memory, the user experience is reduced. So, the UI manager we are creating here does not need to manage the release of the UI, just give a UI panel name that is responsible for calling the manager on and off.
As for UI release, you can design a mechanism that, except for the current scenario, will automatically release enabled UI resources within 15 minutes without enabling them again (somewhat mimicking GC). The 15-minute counter here detects the number of times the closed panel is used. Each time the panel is opened, the number of times is counted. The closed panel here is the one that was opened. Here, we do not need to record the previous opening times of each panel, the current opening times, just need to increase the number of opening times, give the total number of each panel. During the 15-minute test, if it is at the frequency you set, we can consider it to be used frequently. If it is below the frequency you set, we can consider it to be used infrequently. After 15 minutes, it can be cleaned up. SceneMenu uses the sceneBoot resource sound, but the UI on that panel has been cleaned up. When the player switches to sceneBoot, there is no UI and they have to reload.
When it comes to cleaning up the UI, it’s a case by case (for example, in these two game scenes above, you can see that some of the UI is reusable). For example, a simple data class can be set to null and wait for GC to collect it. For example, a display object may have a parent object and be referenced by other objects, so remove child first and then delete. Since setting null assumes that you know by whom the object is referenced, the reference counting method inside the GC determines whether the object is referenced or not to decide whether to reclaim.
In the case of the Egret engine, the UI is removed from the stage and is generally no longer referenced. Removing objects by omission is easier to detect, but the leak of delete is more subtle. In this respect, each team has its own ideas.
V8 GC mechanism
The above mentioned use of GC to collect, here by the way to review the GC mechanism, V8 implements accurate GC, GC algorithm uses generational garbage collection mechanism. Therefore, V8 divides memory (heap) into the new generation and the old generation.
New generation algorithm
Objects in the new generation tend to be short-lived, use the Scavenge GC algorithm. In the new generation space, the memory space is divided into two parts, namely From space and To space. Of these two Spaces, one must be used and the other free. The newly allocated objects are put into the From space, and when the From space is full, the new generation GC starts. The algorithm checks for viable objects in the From space and copies them To the To space, and destroys deactivated objects. When the copy is complete, swap the From space with the To space, and the GC ends.
Old generation algorithm
The objects in the old generation generally live for a long time and have a large number. Two algorithms are used, namely, the mark clearing algorithm and the mark compression algorithm. Before we talk about algorithms, let’s talk about when objects can appear in old generation space:
-
Insane. Are objects from the Cenozoic era already subjected to the Scavenge algorithm, and if so, to move objects from the Cenozoic era to the older age.
-
The size of objects in the To space exceeds 25%. In this case, objects are moved from the new generation space to the old generation space in order not to affect memory allocation. The old age space is very complex, there are the following Spaces
enum AllocationSpace {
// TODO(v8:7464): Actually map this space's memory as read-only.
RO_SPACE, // Invariant object space
NEW_SPACE, // New generation space for GC replication algorithm
OLD_SPACE, // Old generation resident object space
CODE_SPACE, // Old code object space
MAP_SPACE, // Old map object
LO_SPACE, // Old generation large space object
NEW_LO_SPACE, // New generation large space object
FIRST_SPACE = RO_SPACE,
LAST_SPACE = NEW_LO_SPACE,
FIRST_GROWABLE_PAGED_SPACE = OLD_SPACE,
LAST_GROWABLE_PAGED_SPACE = MAP_SPACE
};
Copy the code
In the old generation, the tag clearing algorithm is started in the following cases:
- When there is no partition of a space
- The object in space exceeds a limit
- Space does not guarantee that objects in the new generation will move into the old generation
In this phase, all objects in the heap are iterated, live objects are marked, and all unmarked objects are destroyed when the marking is complete. When marking large pairs of memory, it can take hundreds of milliseconds to complete a mark.
This can lead to performance issues. To address this issue, V8 switched from the stop-the-world flag to the incremental flag in 2011. During incremental tagging, GC breaks the tagging work into smaller modules, allowing JS application logic to execute between modules for a while without causing the application to stall. But in 2018, THERE was another big breakthrough in GC technology called concurrent markup. This technique allows THE GC to scan and mark objects while allowing JS to run. Object removal will cause heap memory fragmentation, when the fragmentation exceeds a certain limit will start the compression algorithm. During compression, live objects are moved on one side until all objects have been moved and unneeded memory is cleared.
conclusion
The above operation is the overall idea of UI management, which can be reviewed together with the previous scene management, but the game engine is not given. Of course, each team has different practices, corresponding to scene management and UI management. If there is a better method, WE hope we can put forward to learn and communicate together.