4
5
10#include "HAL/LowLevelMemTracker.h"
11#include "Misc/ScopeLock.h"
12#include "ProfilingDebugging/MemoryTrace.h"
13#include "Stats/Stats.h"
27struct FGrowableAllocationBase
52
53
83
84
85
86
87
88
89
93
94
95
96
97
101
102
106
107
114
115
116
120
121
125
126
131
132
152
153
160 checkf(IsEmpty(), TEXT(
"Chunk was not empty when it was destroyed!"));
165
166
167
168
169
178 MaxFreeEntrySize = FMath::Max(Entry->BlockSize, MaxFreeEntrySize);
195 bool bResult =
false;
207
208
222 const uint32 AlignedSize = Align<uint32>(Size, Alignment);
225 const uint32 WastedSize = AlignedSize - Size;
244 if (FindEntry != NULL)
255 uint32 Offset = FindEntry
->Split(AlignedSize
, Alignment
, bDelete
, Padding
, MinAllocationSize
);
259 PrevRef = FindEntry
->Next;
263 FGrowableAllocationBase* Allocation = CreateAllocationStruct();
264 Allocation->Size = AlignedSize;
265 Allocation->Padding = Padding;
266 Allocation->Offset = Offset;
268 Allocation->OwnerType = OwnerType;
270 LLM(FLowLevelMemTracker::Get().OnLowLevelAlloc(ELLMTracker::Default, GetAddressForTracking(Offset), Size));
271 MemoryTrace_Alloc(uint64(GetAddressForTracking(Offset)), Size, Alignment, EMemoryTraceRootHeap::SystemMemory);
274 InitializeAllocationStruct(Allocation);
279 FPlatformMisc::LowLevelOutputDebugStringf(
TEXT(
"Failed to allocate GPU memory (Size: %d)"), AlignedSize);
283 bool Free(FGrowableAllocationBase* Memory)
288 uint64 Padding = Memory->Padding;
289 uint64 Size = Memory->Size;
290 uint64 AllocationSize = Padding + Size;
291 uint32 Offset = Memory->Offset;
293 LLM(FLowLevelMemTracker::Get().OnLowLevelFree(ELLMTracker::Default, GetAddressForTracking(Offset)));
294 MemoryTrace_Free(uint64(GetAddressForTracking(Offset)), EMemoryTraceRootHeap::SystemMemory);
297 DestroyAllocationStruct(Memory);
312 if (Entry && (Offset + Size) == Entry
->Location)
323 MaxFreeEntrySize = FMath::Max(MaxFreeEntrySize, Prev->BlockSize);
328 MaxFreeEntrySize = FMath::Max(MaxFreeEntrySize, Entry->BlockSize);
346 MaxFreeEntrySize = FMath::Max(MaxFreeEntrySize, Prev->BlockSize);
354 MaxFreeEntrySize = FMath::Max(MaxFreeEntrySize, NewFree->BlockSize);
367 FPlatformMisc::LowLevelOutputDebugStringf(
TEXT(
"Full Free List:\n"));
369 TMap<uint64, uint32> FreeBlockSizeHistogram;
379 if (FreeBlockSizeHistogram.Contains(Entry->BlockSize))
381 FreeBlockSizeHistogram.FindChecked(Entry->BlockSize)++;
385 FreeBlockSizeHistogram.Add(Entry->BlockSize) = 1;
394 FPlatformMisc::LowLevelOutputDebugStringf(
TEXT(
"Num Blocks: %d Total Size: %d\n"), Count, Total);
396 for (
auto It = FreeBlockSizeHistogram.CreateIterator(); It; ++It)
398 FPlatformMisc::LowLevelOutputDebugStringf(
TEXT(
" %d, %d\n"), It.Key(), It.Value());
420
421
422
423
424
425 bool CanFit(uint64 AlignedSize, uint32 Alignment)
428 uint32 AlignedLocation = Align(
Location, Alignment);
435
436
437
438
439
440
441
442 uint32
Split(uint64 UsedSize, uint32 Alignment,
bool &bDelete, uint32& Padding, uint32 MinSize)
445 check((UsedSize & (Alignment - 1)) == 0);
448 uint32 FreeLoc = Align(
Location, Alignment);
452 uint64 AllocationSize = UsedSize + uint64(Padding);
455 if (
BlockSize - AllocationSize >= MinSize)
509
510
511template <
typename ChunkAllocatorType,
typename GrowableAllocationBaseType>
517
518
519
520
521
522
539
540
563 GrowableAllocationBaseType*
Malloc(uint32 Size, uint32 Alignment, int32 OwnerType)
622#if ALLOCATION_HISTOGRAM_DETAILED
637 bool Free(GrowableAllocationBaseType* Memory)
661#if ALLOCATION_HISTOGRAM_DETAILED
782#if ALLOCATION_HISTOGRAM_DETAILED
800
801
802
803
830
831
832
833
834
900#if ALLOCATION_HISTOGRAM_DETAILED
#define checkf(expr, format,...)
#define UE_BUILD_SHIPPING
#define ALLOCATION_HISTOGRAM
FWindowsCriticalSection FCriticalSection
virtual uint64 GetWasteApproximation()
virtual ~FGrowableMallocBase()
uint32 Split(uint64 UsedSize, uint32 Alignment, bool &bDelete, uint32 &Padding, uint32 MinSize)
FFreeEntry(FFreeEntry *NextEntry, uint32 InLocation, uint64 InSize)
bool CanFit(uint64 AlignedSize, uint32 Alignment)
FGrowableMallocChunk(uint64 InSize, uint32 Type, FCriticalSection *InCriticalSection)
virtual void DestroyInternalMemory()=0
virtual bool DoesChunkContainAllocation(const FGrowableAllocationBase *Allocation)=0
FGrowableAllocationBase * Malloc(uint32 Size, uint32 Alignment, uint32 MinAllocationSize, int32 OwnerType)
bool Free(FGrowableAllocationBase *Memory)
static const uint32 MaxFreeEntrySizeDirty
virtual void * GetAddressForTracking(uint32 Offset)=0
void ShowFullAllocationList()
virtual void DestroyAllocationStruct(FGrowableAllocationBase *Allocation)
virtual ~FGrowableMallocChunk()
bool CanFitEntry(uint32 Size, uint32 Alignment)
void GetAllocationInfo(uint64 &Used, uint64 &Free)
virtual FGrowableAllocationBase * CreateAllocationStruct()=0
FCriticalSection * CriticalSection
virtual uint64 CreateInternalMemory(uint64 Size)=0
virtual void InitializeAllocationStruct(FGrowableAllocationBase *Allocation)=0
virtual bool DoesChunkContainAddress(const void *Address)=0
UE_NODISCARD_CTOR FScopeLock(FCriticalSection *InSynchObject)
uint64 TotalAllocationSize
void OutOfMemory(uint32 Size)
ChunkAllocatorType * CreateAllocChunk(uint64 Size)
TGenericGrowableAllocator(uint64 InitialSize, uint32 InType, uint32 InSubAllocationAlignment, FName InStatRegionName, const FName *InOwnerTypeToStatIdMap, void *InUserData)
TArray< ChunkAllocatorType * > AllocChunks
void UpdateMemoryStatMaxSizes()
virtual ~TGenericGrowableAllocator()
FCriticalSection CriticalSection
void RemoveAllocChunk(ChunkAllocatorType *Chunk)
void ShowAllocationInfo()
void ShowFullAllocationInfo()
bool DoesAllocatorContainAddress(const void *Address)
const uint32 SubAllocationAlignment
const FName * OwnerTypeToStatIdMap
GrowableAllocationBaseType * Malloc(uint32 Size, uint32 Alignment, int32 OwnerType)
bool Free(GrowableAllocationBaseType *Memory)
void GetAllocationInfo(uint32 &Chunks, uint64 &Used, uint64 &Free)