Ark Server API (ASA) - Wiki
Loading...
Searching...
No Matches
PageCache.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2
3#pragma once
4
5// HEADER_UNIT_SKIP - Not included directly
6
7#include "CoreTypes.h"
8#include "HAL/CriticalSection.h"
9#include "HAL/MallocBinnedCommon.h"
10
12{
14
15 uint8* LowAddress;
17 size_t PageSize;
18 uint32 NumPages;
19 uint32 MemSize;
20 uint32 SweepPage;
24
25 uint64 CommitHits;
27
28
31
32 uint32 AddrToPageIndex(void* Addr) const
33 {
34 uint32 PageIndex = (((uint8*)Addr) - LowAddress) / PageSize;
35 check(PageIndex < NumPages && (uint8*)Addr >= LowAddress);
36 return PageIndex;
37 }
38
39 void* PageIndexToAddr(uint32 PageIndex) const
40 {
41 check(PageIndex < NumPages);
42 return (void*)(LowAddress + size_t(PageIndex) * PageSize);
43 }
44
45 bool IsCommitted(void* Addr) const
46 {
47 uint32 PageIndex = AddrToPageIndex(Addr);
48 bool bCommitted = CurrentlyCommitted.IsAllocated(PageIndex);
49 check(bCommitted || NotPendingDecommit.IsAllocated(PageIndex)); // can't be decommited and pending decommit
50 return bCommitted;
51 }
52
53 bool IsPendingDecommit(void* Addr) const
54 {
55 uint32 PageIndex = AddrToPageIndex(Addr);
56 bool bPendingDecommit = !NotPendingDecommit.IsAllocated(PageIndex);
57 check(!bPendingDecommit || CurrentlyCommitted.IsAllocated(PageIndex)); // can't be decommited and pending decommit
58 return bPendingDecommit;
59 }
60
61 void Commit(void* Addr)
62 {
63 uint32 PageIndex = AddrToPageIndex(Addr);
64 CurrentlyCommitted.AllocBit(PageIndex);
65 }
66 void Decommit(void* Addr)
67 {
68 uint32 PageIndex = AddrToPageIndex(Addr);
69 CurrentlyCommitted.FreeBit(PageIndex);
70 }
71 void MarkPendingDecommit(void* Addr)
72 {
73 uint32 PageIndex = AddrToPageIndex(Addr);
74 check(IsCommitted(Addr));
75 NotPendingDecommit.FreeBit(PageIndex);
76 }
77 void UnMarkPendingDecommit(void* Addr)
78 {
79 uint32 PageIndex = AddrToPageIndex(Addr);
80 check(IsCommitted(Addr));
81 NotPendingDecommit.AllocBit(PageIndex);
82 }
83
84public:
85
86 FPageCache(void *InLowAdress, void* InHighAddress, size_t InPageSize)
87 : LowAddress((uint8*)InLowAdress)
88 , HighAddress((uint8*)InHighAddress)
89 , PageSize(InPageSize)
90 , NumPages(0)
91 , MemSize(0)
92 , SweepPage(0)
95 {
96 }
97
99 {
100 check(PageSize && LowAddress && HighAddress > LowAddress);
102 MemSize = FBitTree::GetMemoryRequirements(NumPages);
103 return MemSize * 2;
104 }
105
106 void InitPageCache(void* Memory)
107 {
108 check(NumPages && MemSize);
109 FScopeLock Lock(&CriticalSection);
111 CurrentlyCommitted.FBitTreeInit(NumPages, Memory, MemSize, false);
112 NotPendingDecommit.FBitTreeInit(NumPages, (uint8*)Memory + MemSize, MemSize, true);
113 }
114
115 size_t MarkForPendingDecommit(void *InAddr, size_t Size)
116 {
117 check(Size > 0 && IsAligned(Size, PageSize));
118 uint32 StartPage = AddrToPageIndex(InAddr);
119 uint32 EndPage = StartPage + Size / PageSize;
120
121 uint32 NumFound = 0;
122
123 FScopeLock Lock(&CriticalSection);
124 // this loop could be accelerated by using the hierarchical info in the bit tree
125 for (uint32 Index = StartPage; Index < EndPage; Index++)
126 {
127 if (CurrentlyCommitted.IsAllocated(Index) && NotPendingDecommit.IsAllocated(Index))
128 {
129 NumFound++;
131 NotPendingDecommit.FreeBit(Index);
132 }
133 }
134 return size_t(NumFound) * PageSize;
135 }
136
137 template<typename T>
138 size_t Commit(void *InAddr, size_t Size, size_t& OutUnPending, T&& CommitFunction)
139 {
140 check(Size > 0 && IsAligned(Size, PageSize));
143
147 // this loop could be accelerated by using the hierarchical info in the bit tree
148 uint32 NumFound = 0;
151 {
153 {
155 {
158 NumUnPending++;
160 }
161 }
162 else
163 {
164 NumFound++;
171 {
173 {
175 }
177 }
179 }
180 }
182 {
184 }
188 return size_t(NumFound) * PageSize;
189 }
190 template<typename T>
191 size_t ForceDecommit(void *InAddr, size_t Size, size_t& OutUnPending, T&& DecommitFunction)
192 {
193 check(Size > 0 && IsAligned(Size, PageSize));
196
200 // this loop could be accelerated by using the hierarchical info in the bit tree
201 uint32 NumFound = 0;
204 {
206 {
208 {
212 NumUnPending++;
213 }
214 NumFound++;
220 {
222 {
224 }
226 }
228 }
229 }
231 {
233 }
235 return size_t(NumFound) * PageSize;
236 }
237 template<typename T>
238 size_t DecommitPending(size_t Size, T&& DecommitFunction)
239 {
240 if (!NumPages)
241 {
242 return 0; // this page cache was never really set up, nothing to sweep
243 }
244 check(Size > 0 && IsAligned(Size, PageSize));
246
249 uint32 NumFound = 0;
251
252 while (NumFound < NumNeed)
253 {
256 if (Index == MAX_uint32)
257 {
258 SweepPage = 0;
259 break;
260 }
267 NumFound++;
271 {
273 {
275 }
277 }
279 SweepPage = Index + 1;
280 if (SweepPage >= NumPages)
281 {
282 SweepPage = 0;
283 break;
284 }
285 }
287 {
289 }
290 return size_t(NumFound) * PageSize;
291 }
292 template<typename T>
293 size_t TryDecommitPending(size_t Size, T&& DecommitFunction)
294 {
295 if (!NumPages)
296 {
297 return 0; // this page cache was never really set up, nothing to sweep
298 }
299 check(Size > 0 && IsAligned(Size, PageSize));
301
304 uint32 NumFound = 0;
306
307 auto DecommitRange = [&]()
308 {
310
312 {
318
321 {
324 }
325 }
326 };
327 while (NumFound < NumNeed)
328 {
331 if (Index == MAX_uint32)
332 {
333 SweepPage = 0;
334 break;
335 }
338
340 {
342 {
344 }
346 }
348 SweepPage = Index + 1;
349 if (SweepPage >= NumPages)
350 {
351 SweepPage = 0;
352 break;
353 }
354 }
356 {
358 }
359 return size_t(NumFound) * PageSize;
360 }
362 {
363 FScopeLock Lock(&CriticalSection);
364 return size_t(PendingDecommittedPages) * PageSize;
365 }
367 {
368 FScopeLock Lock(&CriticalSection);
369 return 100.0f * float(CommitHits) / float(CommitHits + CommitMisses + 1); // +1 to avoid divide by zero
370 }
371};
#define check(expr)
#define MAX_uint32
FWindowsCriticalSection FCriticalSection
uint32 PendingDecommittedPages
Definition PageCache.h:23
uint32 AddrToPageIndex(void *Addr) const
Definition PageCache.h:32
FPageCache(void *InLowAdress, void *InHighAddress, size_t InPageSize)
Definition PageCache.h:86
void InitPageCache(void *Memory)
Definition PageCache.h:106
void MarkPendingDecommit(void *Addr)
Definition PageCache.h:71
bool IsCommitted(void *Addr) const
Definition PageCache.h:45
size_t GetFreeableMemory()
Definition PageCache.h:361
size_t Commit(void *InAddr, size_t Size, size_t &OutUnPending, T &&CommitFunction)
Definition PageCache.h:138
uint32 NumPages
Definition PageCache.h:18
void * PageIndexToAddr(uint32 PageIndex) const
Definition PageCache.h:39
bool IsPendingDecommit(void *Addr) const
Definition PageCache.h:53
uint32 MemSize
Definition PageCache.h:19
void UnMarkPendingDecommit(void *Addr)
Definition PageCache.h:77
uint32 GetMemoryRequirements()
Definition PageCache.h:98
uint32 CommittedPages
Definition PageCache.h:21
size_t TryDecommitPending(size_t Size, T &&DecommitFunction)
Definition PageCache.h:293
FBitTree CurrentlyCommitted
Definition PageCache.h:29
FCriticalSection CriticalSection
Definition PageCache.h:13
uint8 * HighAddress
Definition PageCache.h:16
uint64 CommitMisses
Definition PageCache.h:26
size_t MarkForPendingDecommit(void *InAddr, size_t Size)
Definition PageCache.h:115
void Decommit(void *Addr)
Definition PageCache.h:66
size_t ForceDecommit(void *InAddr, size_t Size, size_t &OutUnPending, T &&DecommitFunction)
Definition PageCache.h:191
uint8 * LowAddress
Definition PageCache.h:15
size_t DecommitPending(size_t Size, T &&DecommitFunction)
Definition PageCache.h:238
size_t PageSize
Definition PageCache.h:17
float GetHitRate()
Definition PageCache.h:366
uint32 DecommittedPages
Definition PageCache.h:22
void Commit(void *Addr)
Definition PageCache.h:61
uint64 CommitHits
Definition PageCache.h:25
uint32 SweepPage
Definition PageCache.h:20
FBitTree NotPendingDecommit
Definition PageCache.h:30