Until day 342, the Clear
function on arenas looked like this:
inline void InitializeArena(memory_arena *Arena, memory_index Size, void *Base) { Arena->Size = Size; Arena->Base = (uint8 *)Base; Arena->Used = 0; Arena->TempCount = 0; Arena->MinimumBlockSize = 0; } inline void Clear(memory_arena *Arena) { InitializeArena(Arena, Arena->Size, Arena->Base); }
So in this case, clearing the arena is basically free. But on day 342, after having added support for growing arenas, the clear function has changed to:
inline void FreeLastBlock(memory_arena *Arena) { void *Free = Arena->Base; memory_block_footer *Footer = GetFooter(Arena); Arena->Base = Footer->Base; Arena->Size = Footer->Size; Arena->Used = Footer->Used; Platform.DeallocateMemory(Free); --Arena->BlockCount; } inline void Clear(memory_arena *Arena) { while(Arena->BlockCount > 0) { FreeLastBlock(Arena); } }
Does this means that arenas cannot be reinitialized like before with just some assignment, without deallocating the memory? Isn't that a step back?
Maybe we can use temporary_memory
, because as long as we allocate off of the same block, there is no actual deallocation:
inline void EndTemporaryMemory(temporary_memory TempMem) { memory_arena *Arena = TempMem.Arena; while(Arena->Base != TempMem.Base) { FreeLastBlock(Arena); } Assert(Arena->Used >= TempMem.Used); Arena->Used = TempMem.Used; Assert(Arena->TempCount > 0); --Arena->TempCount; }
So ending temporary memories is still "fast" without deallocating, but only if we didn't pushed too much on the temporary memory, because in that case, EndTemporaryMemory
will actually free the additional blocks.
This means that we can only guarantee that ending the temporary memory that it's "fast" if we don't overflow the current block, because otherwise we'll have to deallocate memory.
So did we really lose the ability to clear the memory with just some assignments? Or at least we lost the guarantee that it'll be fast (because we may have pushed too much on the temporary memory)? I thought that it was important in games to avoid deallocating the memory every frame.
teransYes
So did we really lose the ability to clear the memory with just some assignments?
teransIt's slower, but keep in mind that there will not be much calls to
Or at least we lost the guarantee that it'll be fast (because we may have pushed too much on the temporary memory)? I thought that it was important in games to avoid deallocating the memory every frame.
VirtualAlloc
and VirtualFree
as, if I remember correctly, there aren't a lot of memory blocks allocated (I believe it's less than 10 but I didn't measure that).
When the memory lifetime is long there is no issue with this as it results with rare call to VirtualAlloc
and VirtualFree
.
When the memory lifetime is a frame or less, we generally have blocks big enough (you can do a lot with 1MB) to accommodate lots of small memory allocations without the need to create a lot of new blocks; and things that needs more than a single block size (which are less common) still get a big continuous block at the cost of a VirtualAlloc
and a VirtualFree
call.
In the end, if you want to know the impact on performance, you need to profile both systems. I suspect the difference will be very small.