Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
CachedOSVeryLargePageAllocator.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4#include "Containers/List.h"
5#include "CoreTypes.h"
6#include "HAL/Allocators/CachedOSPageAllocator.h"
7#include "HAL/CriticalSection.h"
8#include "HAL/PlatformMemory.h"
9#include "HAL/UnrealMemory.h"
10
11
12#ifndef UE_USE_VERYLARGEPAGEALLOCATOR_FALLBACKPATH
13#define UE_USE_VERYLARGEPAGEALLOCATOR_FALLBACKPATH UE_USE_VERYLARGEPAGEALLOCATOR
14#endif // UE_USE_VERYLARGEPAGEALLOCATOR_FALLBACKPATH
15
17
18#if PLATFORM_64BITS
19#define CACHEDOSVERYLARGEPAGEALLOCATOR_BYTE_LIMIT (128*1024*1024)
20#else
21#define CACHEDOSVERYLARGEPAGEALLOCATOR_BYTE_LIMIT (16*1024*1024)
22#endif
23//#define CACHEDOSVERYLARGEPAGEALLOCATOR_MAX_CACHED_OS_FREES (CACHEDOSVERYLARGEPAGEALLOCATOR_BYTE_LIMIT/(1024*64))
24#define CACHEDOSVERYLARGEPAGEALLOCATOR_MAX_CACHED_OS_FREES (256)
25
26
27#ifndef UE_VERYLARGEPAGEALLOCATOR_TAKEONALL64KBALLOCATIONS
28#define UE_VERYLARGEPAGEALLOCATOR_TAKEONALL64KBALLOCATIONS 1
29#endif
30
31#ifndef UE_VERYLARGEPAGEALLOCATOR_RESERVED_SIZE_IN_GB
32#define UE_VERYLARGEPAGEALLOCATOR_RESERVED_SIZE_IN_GB 2 //default to 2GB
33#endif
34
35
36#ifndef UE_VERYLARGEPAGEALLOCATOR_PAGESIZE_KB
37#define UE_VERYLARGEPAGEALLOCATOR_PAGESIZE_KB 2048 //default to 2MB
38#endif
39class FCachedOSVeryLargePageAllocator
40{
41 // we make the address space twice as big as we need and use the 1st have for small pool allocations, the 2nd half is used for other allocations that are still == SizeOfSubPage
42#if UE_VERYLARGEPAGEALLOCATOR_TAKEONALL64KBALLOCATIONS
43 static constexpr uint64 AddressSpaceToReserve = ((1024LL * 1024LL * 1024LL) * UE_VERYLARGEPAGEALLOCATOR_RESERVED_SIZE_IN_GB * 2LL);
44 static constexpr uint64 AddressSpaceToReserveForSmallPool = AddressSpaceToReserve / 2;
45#else
46 static constexpr uint64 AddressSpaceToReserve = ((1024 * 1024 * 1024LL) * UE_VERYLARGEPAGEALLOCATOR_RESERVED_SIZE_IN_GB);
47 static constexpr uint64 AddressSpaceToReserveForSmallPool = AddressSpaceToReserve;
48#endif
49 static constexpr uint64 SizeOfLargePage = (UE_VERYLARGEPAGEALLOCATOR_PAGESIZE_KB * 1024);
50 static constexpr uint64 SizeOfSubPage = (1024 * 64);
51 static constexpr uint64 NumberOfLargePages = (AddressSpaceToReserve / SizeOfLargePage);
52 static constexpr uint64 NumberOfSubPagesPerLargePage = (SizeOfLargePage / SizeOfSubPage);
53public:
54
55 FCachedOSVeryLargePageAllocator()
56 : bEnabled(true)
57 , CachedFree(0)
58 {
59 Init();
60 }
61
62 ~FCachedOSVeryLargePageAllocator()
63 {
64 // this leaks everything!
65 }
66
67 void* Allocate(SIZE_T Size, uint32 AllocationHint = 0, FCriticalSection* Mutex = nullptr);
68
69 void Free(void* Ptr, SIZE_T Size, FCriticalSection* Mutex = nullptr, bool ThreadIsTimeCritical = false);
70
71 void FreeAll(FCriticalSection* Mutex = nullptr);
72
73 // Refresh cached os allocator if needed. Will preallocate / reduce backstore if preallocation is enabled
74 void Refresh();
75
76 void UpdateStats();
77
78 uint64 GetCachedFreeTotal()
79 {
80 return CachedFree + CachedOSPageAllocator.GetCachedFreeTotal();
81 }
82
83 FORCEINLINE bool IsPartOf(const void* Ptr)
84 {
85 if (((uintptr_t)Ptr - AddressSpaceReserved) < AddressSpaceToReserveForSmallPool)
86 {
87 return true;
88 }
89 return false;
90 }
91
92private:
93
94 void Init();
95 void ShrinkEmptyBackStore(int32 NewEmptyBackStoreSize, FMemory::AllocationHints AllocationHint);
96
97 bool bEnabled;
98 uintptr_t AddressSpaceReserved;
99 uintptr_t AddressSpaceReservedEndSmallPool;
100 uintptr_t AddressSpaceReservedEnd;
101 uint64 CachedFree;
102 int32 EmptyBackStoreCount[FMemory::AllocationHints::Max];
103 int32 CommitedLargePagesCount[FMemory::AllocationHints::Max];
104
105 FPlatformMemory::FPlatformVirtualMemoryBlock Block;
106
107 struct FLargePage : public TIntrusiveLinkedList<FLargePage>
108 {
109 uintptr_t FreeSubPages[NumberOfSubPagesPerLargePage];
110 int32 NumberOfFreeSubPages;
111 uint32 AllocationHint;
112
113 uintptr_t BaseAddress;
114
115 void Init(void* InBaseAddress)
116 {
117 BaseAddress = (uintptr_t)InBaseAddress;
118 NumberOfFreeSubPages = NumberOfSubPagesPerLargePage;
119 uintptr_t Ptr = BaseAddress;
120 for (int i = 0; i < NumberOfFreeSubPages; i++)
121 {
122 FreeSubPages[i] = Ptr;
123 Ptr += SizeOfSubPage;
124 }
125 }
126
127 void Free(void* Ptr)
128 {
129 FreeSubPages[NumberOfFreeSubPages++] = (uintptr_t)Ptr;
130 }
131
132 void* Allocate()
133 {
134 void* ret = nullptr;
135 if (NumberOfFreeSubPages)
136 {
137 ret = (void*)FreeSubPages[--NumberOfFreeSubPages];
138 }
139 return ret;
140 }
141 };
142
143 FLargePage* FreeLargePagesHead[FMemory::AllocationHints::Max]; // no backing store
144
145 FLargePage* UsedLargePagesHead[FMemory::AllocationHints::Max]; // has backing store and is full
146
147 FLargePage* UsedLargePagesWithSpaceHead[FMemory::AllocationHints::Max]; // has backing store and still has room
148
149 FLargePage* EmptyButAvailableLargePagesHead[FMemory::AllocationHints::Max]; // has backing store and is empty
150
151 FLargePage LargePagesArray[NumberOfLargePages];
152
153 TCachedOSPageAllocator<CACHEDOSVERYLARGEPAGEALLOCATOR_MAX_CACHED_OS_FREES, CACHEDOSVERYLARGEPAGEALLOCATOR_BYTE_LIMIT> CachedOSPageAllocator;
154
155};
156CORE_API extern bool GEnableVeryLargePageAllocator;
157
158#endif // UE_USE_VERYLARGEPAGEALLOCATOR
#define UE_USE_VERYLARGEPAGEALLOCATOR