We have multiple memory pools knocking about, it's something I am very familiar with as it often goes wrong when people don't use it properly, but a good memory pool system can speed up your game massively.
To give you a few examples.
Scratchpad
INCREDIBLY DANAGEROUS!!! but incredibly fast.
We use a scratchpad when we just need a block of memory within a subroutine. an example pseudo code would be
void init(int size)
{
base = maloc(size);
}
void * alloc(size)
{
oldptr = base;
base+=size;
return oldptr;
}
void free(int size)
{
base-=size;
}
You can see why it is so dangerous
Used correctly it is about as fast as you can get.
Simple pool
A simple pool is much safer, but can suffer from fragmentation. It is a double linked list of memory fragments.
This produces an overhead on each memory allocation, you attach a header to each allocation. So each alloc consumes requested memory + header size bytes of memory.
When you free a block of memory, you look at the last and next blocks. If either of those is free you join this allocation to it... kind of hard to explain.
I'll try a diagram. F is a free block, A is an allocated block. So if you start off with this structure
A1 A2 F1 A3 A4 F2
Then free A2 you end up with F1 growing into the newly available space and end up with this structure
A1 F1 A3 A4 F2
If you then free A3 , F1 grows again... in the other direction
A1 F1 A4 F2
Finally freeing A4 not only grows F1 a third time, but merges F1 and F2
A1 F1
The last type of allocator we typically use is a block based system. This is used when we know we would get fragmentation and we have a good idea of the size of each allocation
We just allocate an array of blocks of memory and mark them as free. When you ask for an allocation you are just given the first free one.
This can never fragment, and is very fast, but it is also very wasteful. Say you decide that 4K is a valid block size, every block will be 4K, so if you only need 3K , you have wasted 1K of ram.
This is just a walk through of the basic structure of the sorts of memory allocators we use and why, as usual the real world code gets more complex. Fallbacks, error handling, and a million other things that people add because they had a bug and made it general case instead of situational... but that's lfe I guess.
Hope this helps you come up with a plan.