UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
VirtualAllocator.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "CoreTypes.h"
9#include "Misc/ScopeLock.h"
11
13{
14 struct FFreeLink
15 {
16 void *Ptr = nullptr;
17 FFreeLink* Next = nullptr;
18 };
19
20 struct FPerBlockSize
21 {
22 int64 AllocBlocksSize = 0;
23 int64 FreeBlocksSize = 0;
24 FFreeLink* FirstFree = nullptr;
25 };
26
27 FCriticalSection CriticalSection;
28
29 uint8* LowAddress;
30 uint8* HighAddress;
31
32 size_t TotalSize;
33 size_t PageSize;
34 size_t MaximumAlignment;
35
36 uint8* NextAlloc;
37
38 FFreeLink* RecycledLinks;
39 int64 LinkSize;
40
41 bool bBacksMalloc;
42
43 FPerBlockSize Blocks[64];
44
45 void FreeVirtualByBlock(void* Ptr, FPerBlockSize& Block, size_t AlignedSize)
46 {
47 // already locked
48 if (!RecycledLinks)
49 {
50 void *Alloc;
51 // If we ARE malloc, then we know we can (and must) commit part of our range for free links. Otherwise, we can just use malloc (and can't use our VM space anyway)
52 if (bBacksMalloc)
53 {
54 Alloc = AllocNewVM(MaximumAlignment);
55 uint32 Pages = MaximumAlignment / FPlatformMemory::FPlatformVirtualMemoryBlock::GetVirtualSizeAlignment();
56 check(Pages && MaximumAlignment % FPlatformMemory::FPlatformVirtualMemoryBlock::GetVirtualSizeAlignment() == 0);
58 VMBlock.Commit();
59 }
60 else
61 {
62 Alloc = FMemory::Malloc(MaximumAlignment);
63 }
64 for (int32 Index = 0; (Index + 1) * sizeof(FFreeLink) <= MaximumAlignment; Index++)
65 {
66 FFreeLink* NewLink = new ((void*)(((uint8*)Alloc + Index * sizeof(FFreeLink)))) FFreeLink;
67 NewLink->Next = RecycledLinks;
68 RecycledLinks = NewLink;
69 }
70 LinkSize += MaximumAlignment;
71 }
72
73 FFreeLink* Link = RecycledLinks;
74 RecycledLinks = Link->Next;
75 check(!Link->Ptr && Ptr);
76 Link->Ptr = Ptr;
77 Link->Next = Block.FirstFree;
78 Block.FirstFree = Link;
79
80 Block.FreeBlocksSize += AlignedSize;
81 }
82protected:
84 virtual uint8* AllocNewVM(size_t AlignedSize)
85 {
86 uint8* Result = NextAlloc;
87 check(IsAligned(Result, MaximumAlignment) && IsAligned(AlignedSize, MaximumAlignment));
88 NextAlloc = Result + AlignedSize;
89 SpaceConsumed = NextAlloc - LowAddress;
90 return Result;
91 }
92
93public:
94
96 : LowAddress((uint8*)InLowAdress)
97 , HighAddress((uint8*)InHighAddress)
98 , PageSize(InPageSize)
99 , MaximumAlignment(FMath::Max(InMaximumAlignment, InPageSize))
100 , NextAlloc((uint8*)InLowAdress)
101 , RecycledLinks(nullptr)
102 , LinkSize(0)
103 , bBacksMalloc(bInBacksMalloc)
104 , SpaceConsumed(0)
105 {
106 TotalSize = HighAddress - LowAddress;
107 check(LowAddress && HighAddress && LowAddress < HighAddress && IsAligned(LowAddress, MaximumAlignment));
108 }
109
110 virtual ~FVirtualAllocator() = default;
111
112 uint32 GetPagesForSizeAndAlignment(size_t Size, size_t Alignment = 1) const
113 {
115 size_t SizeAndAlignment = FMath::Max(Align(Size, Alignment), PageSize);
116 if (SizeAndAlignment * 2 >= TotalSize)
117 {
118 // this is hack, MB3 will ask for tons of virtual and never free it, so we won't round up to power of two
119 size_t Pages = SizeAndAlignment / PageSize;
120 check(Pages == uint32(Pages)); // overflow of uint32
121 return uint32(Pages);
122 }
123 size_t BlockIndex = FMath::CeilLogTwo64(FMath::Max(SizeAndAlignment, PageSize));
124 size_t AlignedSize = size_t(1) << BlockIndex;
125 check(AlignedSize % PageSize == 0);
126 size_t Pages = AlignedSize / PageSize;
127 check(Pages == uint32(Pages)); // overflow of uint32
128 return uint32(Pages);
129 }
130
131 void* AllocateVirtualPages(uint32 NumPages, size_t AlignmentForCheck = 1)
132 {
134
135
136 size_t BlockIndex = FMath::CeilLogTwo64(NumPages * PageSize);
137 size_t AlignedSize = size_t(1) << BlockIndex;
138 bool bHackForHugeBlock = false;
139 if (size_t(NumPages) * PageSize * 2 >= TotalSize)
140 {
141 // this is hack, MB3 will ask for tons of virtual and never free it, so we won't round up to power of two
142 AlignedSize = size_t(NumPages) * PageSize;
143 bHackForHugeBlock = true;
144 }
145 FPerBlockSize& Block = Blocks[BlockIndex];
146
147 FScopeLock Lock(&CriticalSection);
148
149
150 uint8* Result;
151 if (Block.FirstFree)
152 {
154 Result = (uint8*)Block.FirstFree->Ptr;
155 check(Result);
156 Block.FirstFree->Ptr = nullptr;
157
158 FFreeLink* Next = RecycledLinks;
159 RecycledLinks = Block.FirstFree;
160 Block.FirstFree = Block.FirstFree->Next;
161 check(!Block.FirstFree || Block.FirstFree->Ptr);
162 RecycledLinks->Next = Next;
163
164 check(IsAligned(Result, FMath::Min(AlignedSize, MaximumAlignment)));
165 Block.FreeBlocksSize -= AlignedSize;
166 }
167 else
168 {
169 size_t AllocSize = FMath::Max(AlignedSize, MaximumAlignment);
170 uint8* LocalNextAlloc = AllocNewVM(AllocSize);
171 check(IsAligned(LocalNextAlloc, MaximumAlignment));
172
173 uint8* NewNextAlloc = LocalNextAlloc + AllocSize;
174
175 if (NewNextAlloc > HighAddress)
176 {
177 FPlatformMemory::OnOutOfMemory(HighAddress - LowAddress, 0);
178 }
179
180 Block.AllocBlocksSize += AllocSize;
181 Result = LocalNextAlloc;
182 check(Result);
183 LocalNextAlloc += AlignedSize;
185 {
186 FreeVirtualByBlock(LocalNextAlloc, Block, AlignedSize);
187 LocalNextAlloc += AlignedSize;
188 }
189 }
191 return Result;
192 }
193
194 void FreeVirtual(void* Ptr, uint32 NumPages)
195 {
196 if (size_t(NumPages) * PageSize * 2 >= TotalSize)
197 {
198 // this is hack, MB3 will ask for tons of virtual and never free it, so we won't round up to power of two
199 check(!"Huge vm blocks may not be freed.");
200 return;
201 }
202 size_t BlockIndex = FMath::CeilLogTwo64(NumPages * PageSize);
203 size_t AlignedSize = size_t(1) << BlockIndex;
204
205 FPerBlockSize& Block = Blocks[BlockIndex];
206 FScopeLock Lock(&CriticalSection);
207 FreeVirtualByBlock(Ptr, Block, AlignedSize);
208 }
209
227
229 {
230 FScopeLock Lock(&CriticalSection);
231 OutStats.PageSize = PageSize;
232 OutStats.MaximumAlignment = MaximumAlignment;
233 OutStats.VMSpaceTotal = HighAddress - LowAddress;
234 OutStats.VMSpaceConsumed = SpaceConsumed;
235 OutStats.FreeListLinks = LinkSize;
236
237 for (int32 Index = 0; Index < 64; Index++)
238 {
239 OutStats.BlockStats[Index].AllocBlocksSize = Blocks[Index].AllocBlocksSize;
240 OutStats.BlockStats[Index].FreeBlocksSize = Blocks[Index].FreeBlocksSize;
241 }
242 }
243};
constexpr T Align(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:18
constexpr bool IsAligned(T Val, uint64 Alignment)
Definition AlignmentTemplates.h:50
#define check(expr)
Definition AssertionMacros.h:314
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
UE::FPlatformRecursiveMutex FCriticalSection
Definition CriticalSection.h:53
FRWLock Lock
Definition UnversionedPropertySerialization.cpp:921
uint32 Size
Definition VulkanMemory.cpp:4034
int BlockIndex
Definition binka_ue_decode_test.cpp:38
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition AndroidPlatformMemory.h:38
Definition ScopeLock.h:141
Definition VirtualAllocator.h:13
virtual ~FVirtualAllocator()=default
void * AllocateVirtualPages(uint32 NumPages, size_t AlignmentForCheck=1)
Definition VirtualAllocator.h:131
uint32 GetPagesForSizeAndAlignment(size_t Size, size_t Alignment=1) const
Definition VirtualAllocator.h:112
void GetStats(FVirtualAllocatorStats &OutStats)
Definition VirtualAllocator.h:228
void FreeVirtual(void *Ptr, uint32 NumPages)
Definition VirtualAllocator.h:194
virtual uint8 * AllocNewVM(size_t AlignedSize)
Definition VirtualAllocator.h:84
FVirtualAllocator(void *InLowAdress, void *InHighAddress, size_t InPageSize, size_t InMaximumAlignment, bool bInBacksMalloc)
Definition VirtualAllocator.h:95
size_t SpaceConsumed
Definition VirtualAllocator.h:83
U16 Index
Definition radfft.cpp:71
static CORE_API void OnOutOfMemory(uint64 Size, uint32 Alignment)
Definition GenericPlatformMemory.cpp:216
Definition UnrealMathUtility.h:270
size_t AllocBlocksSize
Definition VirtualAllocator.h:212
size_t FreeBlocksSize
Definition VirtualAllocator.h:213
Definition VirtualAllocator.h:216
size_t FreeListLinks
Definition VirtualAllocator.h:223
size_t VMSpaceTotal
Definition VirtualAllocator.h:219
size_t VMSpaceConsumed
Definition VirtualAllocator.h:220
size_t VMSpaceConsumedPeak
Definition VirtualAllocator.h:221
size_t PageSize
Definition VirtualAllocator.h:217
size_t MaximumAlignment
Definition VirtualAllocator.h:218
FVirtualAllocatorStatsPerBlockSize BlockStats[64]
Definition VirtualAllocator.h:225