This is not a problem, per se. I am just soliciting advice about how to bucket allocations that are known to have usefully distinct lifetimes. It’s a memory management technique we’ve been carrying forward through many games now. When we moved to UE4, it was a bad fit, but we kludged something together. Now, under UE5, that kludge is costing more and more to maintain, and we’re seeking a new approach.
The basic idea is you have allocations that are deemed “short term” -- things that are likely to go away pretty quickly, and those that are “long term” -- likely to hang around a long time, potentially the entire lifetime of the game. For example: Render commands come and go within a frame, while FName blocks or Config data stick around forever. By sending those to different memory pages, we increase the likelihood of being able to hand some of those short term pages back to the OS, reducing memory fragmentation.
Before virtual memory became the norm, we used to spatialize the long-term allocations, pushing them to top-down memory pages. The allocations were physically separate, making a clear “largest contiguous block” visible in our memory mapping tools. With UE4 and a new hardware generation, virtual memory became the pattern for everything, and that spatialization wasn’t worth it as much, but keeping the different lifetimes on different pages was still worthwhile.
Under UE4, with GMalloc, we got a little stuck. We couldn’t see a good way to route these lifetime decisions through GMalloc, so we made a freestanding little allocator, a dumb clone of FMallocBinned2, and sent requests through it by means of custom allocator types on TArray, TMap, (TLongTermArray, TLongTermMap) and such. When we saw allocations sticking around between matches, we changed the types to long term types. It was a beast to implement -- this was before Unreal had allocator templates on those container types -- but it did work.
Right now the cost centers for maintaining this are the high number of engine edits needed to support the custom types, which makes taking new engine versions harder, and the dumb clone of FMallocBinned2, which has changed shape a _lot_ between UE4 and UE5.
Has anyone else tried a similar thing with a better approach? Or is the idea just a non-starter?