Hello! For this project me and three of my peers did a deep dive into the GoDot game engine, with each of us focusing on a different aspect of the project. Below are the links to the blogs of my peers, read them to do a dive into the other aspects of the GoDot engine!
Input and Server Architecture: https://jacobb.me/blog/2019/10/12/godot/
Scene structure: https://www.austinlaimos.com/post/game-engine-development-godot
So for this I decided to focus on how GoDot handles memory management. To start I’d like to go over the princaples that they listed in their documentation here: https://docs.godotengine.org/en/3.1/development/cpp/core_types.html#memory-model. Here they talk about the issues with using heap and paged memory build into the language, with heap it talks about how memory can lead to being segmented memory. With paged memory it’s good for temporary memory but falls flat when working with permanent memory. So their solution to this is to use a memory pool model for managing their memory. This allows the programmer to allocate memory as without wasting space. However the issue with this is that you have to do a get function every time you want to access that memory, making it slower than using the heap. So the solution is to use a mix of the three, for small / temporary management they use paged memory, for memory that needs to be accessed quickly they use the heap, and for the rest they use the memory pool!
With that established, lets talk about how they use and implement the memory pool. For this they have three classes that work together. Memory, PoolAllocator, and VectorPool. Lets start with Memory, here is where the engine actually allocates it’s memory. Located in this class is the memNew and memDelete functions, these are used as the main ways to allocate and delete memory within the engine. It is also important to note that they use primarily static memory in this function.
The next part of this equation is the PoolAllocator class, this is exactly what it sounds like it’s the memory pool. This is the slower part of the memory management, however it’s much more space efficient due to it’s ability to defrag itself when allocating memory. This works by allocating a set amount of memory (from the Memory class) on initialization, then it is free to ma mange that memory as it sees fit.
Here we can see the memory pointer tr being given it’s static memory, as well as some other pieces being put together. Next up is how they actually allocate memory, this is done in a few steps. Firstly it checks to see if there is any entries available. By checking this will allow the pool to exit early if needed, saving on time. The next check is done by seeing if there is appropriate sized memory space in the pool, if this fails the first time it’ll run a defrag on the memory chunk then check again. This helps a lot with the best case scenario of this check by doing a quick check, however extends the worst case scenario by checking the pool twice.
Finally if both of these succeed, the pool will place the memory into one of the entries pre defined by the pool. The rest of this class is general memory pool stuff, there’s a resize function, a getter for entries, and the normal deconstructions.
Next is the VectorPool, I’m a bit torn about the exact function of this. It appears to be an abstraction of the memory pool, being where the user actually calls the memory pool. However why the memory pool is abstracted is beyond me as it all seems straight forward.
In conclusion, the memory management in GoDot is extremely streamlined, giving the user a lot of control but abstracts it enough to maintain itself.