UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
MallocBinned.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "Containers/Array.h"
6#include "CoreTypes.h"
10#include "HAL/MemoryBase.h"
11#include "HAL/PlatformAtomics.h"
12#include "HAL/PlatformMutex.h"
14#include "Stats/Stats.h"
15
17
18#define MEM_TIME(st)
19
20//#define USE_LOCKFREE_DELETE
21#define USE_INTERNAL_LOCKS
22#if USE_CACHE_FREED_OS_ALLOCS
23//#define CACHE_FREED_OS_ALLOCS
24#endif
25
26#ifndef USE_OS_SMALL_BLOCK_ALLOC
27#define USE_OS_SMALL_BLOCK_ALLOC PLATFORM_IOS
28#endif //USE_OS_SMALL_BLOCK_ALLOC
29
30#ifndef USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS
31#define USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS (USE_OS_SMALL_BLOCK_ALLOC && PLATFORM_IOS && 0)
32#endif //USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS
33
34#ifdef USE_INTERNAL_LOCKS
35//# define USE_COARSE_GRAIN_LOCKS
36#endif
37
38#if defined USE_LOCKFREE_DELETE
39# define USE_INTERNAL_LOCKS
40# define USE_COARSE_GRAIN_LOCKS
41#endif
42
43#if defined CACHE_FREED_OS_ALLOCS
44 #define MAX_CACHED_OS_FREES (64)
45 #if PLATFORM_64BITS
46 #define MAX_CACHED_OS_FREES_BYTE_LIMIT (64*1024*1024)
47 #else
48 #define MAX_CACHED_OS_FREES_BYTE_LIMIT (16*1024*1024)
49 #endif
50#endif
51
52#if defined USE_INTERNAL_LOCKS && !defined USE_COARSE_GRAIN_LOCKS
53# define USE_FINE_GRAIN_LOCKS
54#endif
55
56#if PLATFORM_64BITS
58#else
60#endif
61
62//when modifying the global allocator stats, if we are using COARSE locks, then all callsites for stat modification are covered by the allocator-wide access guard. Thus the stats can be modified directly.
63//If we are using FINE locks, then we must modify the stats through atomics as the locks are either not actually covering the stat callsites, or are locking specific table locks which is not sufficient for stats.
64#if STATS
65# ifdef USE_COARSE_GRAIN_LOCKS
66# define BINNED_STAT BINNED_STAT_TYPE
67# define BINNED_INCREMENT_STATCOUNTER(counter) (++(counter))
68# define BINNED_DECREMENT_STATCOUNTER(counter) (--(counter))
69# define BINNED_ADD_STATCOUNTER(counter, value) ((counter) += (value))
70# define BINNED_PEAK_STATCOUNTER(PeakCounter, CompareVal) ((PeakCounter) = FMath::Max((PeakCounter), (CompareVal)))
71# else
72# define BINNED_STAT volatile BINNED_STAT_TYPE
73# define BINNED_INCREMENT_STATCOUNTER(counter) (FPlatformAtomics::InterlockedIncrement(&(counter)))
74# define BINNED_DECREMENT_STATCOUNTER(counter) (FPlatformAtomics::InterlockedDecrement(&(counter)))
75# define BINNED_ADD_STATCOUNTER(counter, value) (FPlatformAtomics::InterlockedAdd(&counter, (value)))
76# define BINNED_PEAK_STATCOUNTER(PeakCounter, CompareVal) { \
77 BINNED_STAT_TYPE NewCompare; \
78 BINNED_STAT_TYPE NewPeak; \
79 do \
80 { \
81 NewCompare = (PeakCounter); \
82 NewPeak = FMath::Max((PeakCounter), (CompareVal)); \
83 } \
84 while (FPlatformAtomics::InterlockedCompareExchange(&(PeakCounter), NewPeak, NewCompare) != NewCompare); \
85 }
86# endif
87#else
88# define BINNED_STAT BINNED_STAT_TYPE
89# define BINNED_INCREMENT_STATCOUNTER(counter)
90# define BINNED_DECREMENT_STATCOUNTER(counter)
91# define BINNED_ADD_STATCOUNTER(counter, value)
92# define BINNED_PEAK_STATCOUNTER(PeakCounter, CompareVal)
93#endif
94
105
106#if USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS && ENABLE_LOW_LEVEL_MEM_TRACKER
111#endif //USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS
112
113
114//
115// Optimized virtual memory allocator.
116//
117class FMallocBinned : public FMalloc
118{
119 struct Private;
120
121private:
122
123 // Counts.
124 enum { POOL_COUNT = 41 };
125
127 enum { EXTENDED_PAGE_POOL_ALLOCATION_COUNT = 2 };
128 enum { MAX_POOLED_ALLOCATION_SIZE = 32768+1 };
129
130 // Forward declares.
131 struct FFreeMem;
132 struct FPoolInfo;
133 struct FPoolTable;
134 struct PoolHashBucket;
135
136#ifdef CACHE_FREED_OS_ALLOCS
138 struct FFreePageBlock
139 {
140 void* Ptr;
141 SIZE_T ByteSize;
142
143 FFreePageBlock()
144 {
145 Ptr = nullptr;
146 ByteSize = 0;
147 }
148 };
149#endif
150
152 struct FPoolTable
153 {
154 FPoolInfo* FirstPool;
155 FPoolInfo* ExhaustedPool;
156 uint32 BlockSize;
157#ifdef USE_FINE_GRAIN_LOCKS
158 UE::FPlatformRecursiveMutex CriticalSection;
159#endif
160#if STATS
163
166
168 uint32 ActiveRequests;
169
172
175
178
181
183 uint64 TotalWaste;
184#endif
185 FPoolTable()
186 : FirstPool(nullptr)
187 , ExhaustedPool(nullptr)
188 , BlockSize(0)
189#if STATS
190 , NumActivePools(0)
191 , MaxActivePools(0)
192 , ActiveRequests(0)
194 , MinRequest(0)
195 , MaxRequest(0)
196 , TotalRequests(0)
197 , TotalWaste(0)
198#endif
199 {
200
201 }
202 };
203
204 uint64 TableAddressLimit;
205
206#ifdef USE_LOCKFREE_DELETE
214 bool bFlushingFrees;
216#endif
217
218 UE::FPlatformRecursiveMutex AccessGuard;
219
220 // PageSize dependent constants
221 uint64 MaxHashBuckets;
222 uint64 MaxHashBucketBits;
223 uint64 MaxHashBucketWaste;
224 uint64 MaxBookKeepingOverhead;
226 uint64 PoolBitShift;
227 uint64 IndirectPoolBitShift;
228 uint64 IndirectPoolBlockSize;
230 uint64 HashKeyShift;
232 uint64 PoolMask;
233 uint64 BinnedSizeLimit;
234 uint64 BinnedOSTableIndex;
235
236 // Variables.
237 FPoolTable PoolTable[POOL_COUNT];
238 FPoolTable OsTable;
239 FPoolTable PagePoolTable[EXTENDED_PAGE_POOL_ALLOCATION_COUNT];
240 FPoolTable* MemSizeToPoolTable[MAX_POOLED_ALLOCATION_SIZE+EXTENDED_PAGE_POOL_ALLOCATION_COUNT];
241
242 PoolHashBucket* HashBuckets;
243 PoolHashBucket* HashBucketFreeList;
244
245 uint32 PageSize;
246
247#ifdef CACHE_FREED_OS_ALLOCS
248 FFreePageBlock FreedPageBlocks[MAX_CACHED_OS_FREES];
249 uint32 FreedPageBlocksNum;
250 uint32 CachedTotal;
251#endif
252
253#if STATS
260 BINNED_STAT CurrentAllocs;
261 BINNED_STAT TotalAllocs;
264 double MemTime;
265
266#if USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS
271#endif //USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS
272
273#endif //STATS
274
275#if USE_OS_SMALL_BLOCK_ALLOC
277#endif
278
279public:
280 // FMalloc interface.
281 // InPageSize - First parameter is page size, all allocs from BinnedAllocFromOS() MUST be aligned to this size
282 // AddressLimit - Second parameter is estimate of the range of addresses expected to be returns by BinnedAllocFromOS(). Binned
283 // Malloc will adjust its internal structures to make lookups for memory allocations O(1) for this range.
284 // It is ok to go outside this range, lookups will just be a little slower
285 FMallocBinned(uint32 InPageSize, uint64 AddressLimit);
286
287 virtual void InitializeStatsMetadata() override;
288
289 virtual ~FMallocBinned();
290
295 virtual bool IsInternallyThreadSafe() const override;
296
300 virtual void* Malloc( SIZE_T Size, uint32 Alignment ) override;
301
305 virtual void* Realloc( void* Ptr, SIZE_T NewSize, uint32 Alignment ) override;
306
310 virtual void Free( void* Ptr ) override;
311
319 virtual bool GetAllocationSize(void *Original, SIZE_T &SizeOut) override;
320
321 virtual SIZE_T QuantizeSize(SIZE_T Count, uint32 Alignment) override;
322
326 virtual bool ValidateHeap() override;
327
329 virtual void UpdateStats() override;
330
332 virtual void GetAllocatorStats( FGenericMemoryStats& out_Stats ) override;
333
339 virtual void DumpAllocatorStats( class FOutputDevice& Ar ) override;
340
341 virtual const TCHAR* GetDescriptiveName() override;
342};
343
344#if UE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_7
345# include "HAL/CriticalSection.h"
346#endif
#define TEXT(x)
Definition Platform.h:1272
FPlatformTypes::SIZE_T SIZE_T
An unsigned integer the same size as a pointer, the same as UPTRINT.
Definition Platform.h:1150
FPlatformTypes::TCHAR TCHAR
Either ANSICHAR or WIDECHAR, depending on whether the platform supports wide characters or the requir...
Definition Platform.h:1135
FPlatformTypes::int64 int64
A 64-bit signed integer.
Definition Platform.h:1127
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
FPlatformTypes::uint64 uint64
A 64-bit unsigned integer.
Definition Platform.h:1117
#define DECLARE_DWORD_COUNTER_STAT_EXTERN(CounterName, StatId, GroupId, API)
Definition Stats.h:682
#define DECLARE_MEMORY_STAT_EXTERN(CounterName, StatId, GroupId, API)
Definition Stats.h:687
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
#define DECLARE_LLM_MEMORY_STAT_EXTERN(CounterName, StatId, GroupId, API)
Definition LowLevelMemStats.h:51
#define BINNED_STAT
Definition MallocBinned.h:88
int32 BINNED_STAT_TYPE
Definition MallocBinned.h:59
uint32 Size
Definition VulkanMemory.cpp:4034
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition MallocBinned.h:118
virtual void * Malloc(SIZE_T Size, uint32 Alignment) override
Definition MallocBinned.cpp:1286
virtual void GetAllocatorStats(FGenericMemoryStats &out_Stats) override
Definition MallocBinned.cpp:1020
virtual const TCHAR * GetDescriptiveName() override
Definition MallocBinned.cpp:1812
virtual void InitializeStatsMetadata() override
Definition MallocBinned.cpp:1094
virtual SIZE_T QuantizeSize(SIZE_T Count, uint32 Alignment) override
Definition MallocBinned.cpp:1564
virtual void DumpAllocatorStats(class FOutputDevice &Ar) override
Definition MallocBinned.cpp:1700
virtual bool GetAllocationSize(void *Original, SIZE_T &SizeOut) override
Definition MallocBinned.cpp:1522
virtual void * Realloc(void *Ptr, SIZE_T NewSize, uint32 Alignment) override
Definition MallocBinned.cpp:1421
virtual bool IsInternallyThreadSafe() const override
Definition MallocBinned.cpp:1277
virtual bool ValidateHeap() override
Definition MallocBinned.cpp:1603
virtual ~FMallocBinned()
Definition MallocBinned.cpp:1273
virtual void UpdateStats() override
Definition MallocBinned.cpp:1635
Definition MemoryBase.h:99
Definition OutputDevice.h:133
Definition Array.h:670
Definition OverriddenPropertySet.cpp:45
FPThreadsRecursiveMutex FPlatformRecursiveMutex
Definition AndroidPlatformMutex.h:12
Definition MemoryMisc.h:21
Definition MallocBinned.cpp:41
Definition MallocBinned.cpp:50
Definition MallocBinned.cpp:118