@@ -72,14 +72,6 @@ namespace {
72
72
struct CachedBlock {
73
73
static constexpr u16 CacheIndexMax = UINT16_MAX;
74
74
static constexpr u16 InvalidEntry = CacheIndexMax;
75
- // * ReleaseMemoryUpperBound default is currently 16 KB
76
- // - We arrived at this value after noticing that mapping
77
- // in larger memory regions performs better than releasing
78
- // memory and forcing a cache hit. According to the data,
79
- // it suggests that beyond 16KB, the release execution time is
80
- // longer than the map execution time. In this way, the default
81
- // is dependent on the platform.
82
- static constexpr uptr ReleaseMemoryUpperBound = 1 << 14 ;
83
75
84
76
uptr CommitBase = 0 ;
85
77
uptr CommitSize = 0 ;
@@ -98,9 +90,8 @@ struct CachedBlock {
98
90
template <typename Config> class MapAllocatorNoCache {
99
91
public:
100
92
void init (UNUSED s32 ReleaseToOsInterval) {}
101
- CachedBlock retrieve (UNUSED uptr MaxAllowedFragmentedBytes, UNUSED uptr Size,
102
- UNUSED uptr Alignment, UNUSED uptr HeadersSize,
103
- UNUSED uptr &EntryHeaderPos) {
93
+ CachedBlock retrieve (UNUSED uptr Size, UNUSED uptr Alignment,
94
+ UNUSED uptr HeadersSize, UNUSED uptr &EntryHeaderPos) {
104
95
return {};
105
96
}
106
97
void store (UNUSED Options Options, UNUSED uptr CommitBase,
@@ -343,103 +334,61 @@ class MapAllocatorCache {
343
334
}
344
335
}
345
336
346
- CachedBlock retrieve (uptr MaxAllowedFragmentedBytes, uptr Size,
347
- uptr Alignment, uptr HeadersSize, uptr &EntryHeaderPos)
348
- EXCLUDES(Mutex) {
337
+ CachedBlock retrieve (uptr Size, uptr Alignment, uptr HeadersSize,
338
+ uptr &EntryHeaderPos) EXCLUDES(Mutex) {
349
339
const uptr PageSize = getPageSizeCached ();
350
340
// 10% of the requested size proved to be the optimal choice for
351
341
// retrieving cached blocks after testing several options.
352
342
constexpr u32 FragmentedBytesDivisor = 10 ;
353
- bool FoundOptimalFit = false ;
343
+ bool Found = false ;
354
344
CachedBlock Entry;
355
345
EntryHeaderPos = 0 ;
356
346
{
357
347
ScopedLock L (Mutex);
358
348
CallsToRetrieve++;
359
349
if (EntriesCount == 0 )
360
350
return {};
361
- u16 RetrievedIndex = CachedBlock::InvalidEntry ;
351
+ u32 OptimalFitIndex = 0 ;
362
352
uptr MinDiff = UINTPTR_MAX;
363
-
364
- // Since allocation sizes don't always match cached memory chunk sizes
365
- // we allow some memory to be unused (called fragmented bytes). The
366
- // amount of unused bytes is exactly EntryHeaderPos - CommitBase.
367
- //
368
- // CommitBase CommitBase + CommitSize
369
- // V V
370
- // +---+------------+-----------------+---+
371
- // | | | | |
372
- // +---+------------+-----------------+---+
373
- // ^ ^ ^
374
- // Guard EntryHeaderPos Guard-page-end
375
- // page-begin
376
- //
377
- // [EntryHeaderPos, CommitBase + CommitSize) contains the user data as
378
- // well as the header metadata. If EntryHeaderPos - CommitBase exceeds
379
- // MaxAllowedFragmentedBytes, the cached memory chunk is not considered
380
- // valid for retrieval.
381
- for (u16 I = LRUHead; I != CachedBlock::InvalidEntry;
353
+ for (u32 I = LRUHead; I != CachedBlock::InvalidEntry;
382
354
I = Entries[I].Next ) {
383
355
const uptr CommitBase = Entries[I].CommitBase ;
384
356
const uptr CommitSize = Entries[I].CommitSize ;
385
357
const uptr AllocPos =
386
358
roundDown (CommitBase + CommitSize - Size, Alignment);
387
359
const uptr HeaderPos = AllocPos - HeadersSize;
388
- if (HeaderPos > CommitBase + CommitSize || HeaderPos < CommitBase )
360
+ if (HeaderPos > CommitBase + CommitSize)
389
361
continue ;
390
-
391
- const uptr Diff = roundDown (HeaderPos, PageSize) - CommitBase;
392
-
393
- if (Diff > MaxAllowedFragmentedBytes || Diff >= MinDiff)
362
+ if (HeaderPos < CommitBase ||
363
+ AllocPos > CommitBase + PageSize * MaxUnusedCachePages) {
394
364
continue ;
395
-
396
- MinDiff = Diff ;
397
- RetrievedIndex = I ;
398
- EntryHeaderPos = HeaderPos;
399
-
400
- const uptr OptimalFitThesholdBytes =
365
+ }
366
+ Found = true ;
367
+ const uptr Diff = HeaderPos - CommitBase ;
368
+ // immediately use a cached block if it's size is close enough to the
369
+ // requested size.
370
+ const uptr MaxAllowedFragmentedBytes =
401
371
(CommitBase + CommitSize - HeaderPos) / FragmentedBytesDivisor;
402
- if (Diff <= OptimalFitThesholdBytes) {
403
- FoundOptimalFit = true ;
372
+ if (Diff <= MaxAllowedFragmentedBytes) {
373
+ OptimalFitIndex = I;
374
+ EntryHeaderPos = HeaderPos;
404
375
break ;
405
376
}
377
+ // keep track of the smallest cached block
378
+ // that is greater than (AllocSize + HeaderSize)
379
+ if (Diff > MinDiff)
380
+ continue ;
381
+ OptimalFitIndex = I;
382
+ MinDiff = Diff;
383
+ EntryHeaderPos = HeaderPos;
406
384
}
407
- if (RetrievedIndex != CachedBlock::InvalidEntry ) {
408
- Entry = Entries[RetrievedIndex ];
409
- remove (RetrievedIndex );
385
+ if (Found ) {
386
+ Entry = Entries[OptimalFitIndex ];
387
+ remove (OptimalFitIndex );
410
388
SuccessfulRetrieves++;
411
389
}
412
390
}
413
391
414
- // The difference between the retrieved memory chunk and the request
415
- // size is at most MaxAllowedFragmentedBytes
416
- //
417
- // / MaxAllowedFragmentedBytes \
418
- // +--------------------------+-----------+
419
- // | | |
420
- // +--------------------------+-----------+
421
- // \ Bytes to be released / ^
422
- // |
423
- // (may or may not be commited)
424
- //
425
- // The maximum number of bytes released to the OS is capped by
426
- // ReleaseMemoryUpperBound
427
- //
428
- // TODO : Consider making ReleaseMemoryUpperBound configurable since
429
- // the release to OS API can vary across systems.
430
- if (!FoundOptimalFit && Entry.Time != 0 ) {
431
- const uptr FragmentedBytes =
432
- roundDown (EntryHeaderPos, PageSize) - Entry.CommitBase ;
433
- const uptr MaxUnusedCacheBytes = MaxUnusedCachePages * PageSize;
434
- if (FragmentedBytes > MaxUnusedCacheBytes) {
435
- uptr BytesToRelease =
436
- roundUp (Min<uptr>(CachedBlock::ReleaseMemoryUpperBound,
437
- FragmentedBytes - MaxUnusedCacheBytes),
438
- PageSize);
439
- Entry.MemMap .releaseAndZeroPagesToOS (Entry.CommitBase , BytesToRelease);
440
- }
441
- }
442
-
443
392
return Entry;
444
393
}
445
394
@@ -710,18 +659,8 @@ MapAllocator<Config>::tryAllocateFromCache(const Options &Options, uptr Size,
710
659
FillContentsMode FillContents) {
711
660
CachedBlock Entry;
712
661
uptr EntryHeaderPos;
713
- uptr MaxAllowedFragmentedBytes;
714
- const uptr PageSize = getPageSizeCached ();
715
-
716
- if (LIKELY (!useMemoryTagging<Config>(Options))) {
717
- MaxAllowedFragmentedBytes =
718
- MaxUnusedCachePages * PageSize + CachedBlock::ReleaseMemoryUpperBound;
719
- } else {
720
- MaxAllowedFragmentedBytes = MaxUnusedCachePages * PageSize;
721
- }
722
662
723
- Entry = Cache.retrieve (MaxAllowedFragmentedBytes, Size, Alignment,
724
- getHeadersSize (), EntryHeaderPos);
663
+ Entry = Cache.retrieve (Size, Alignment, getHeadersSize (), EntryHeaderPos);
725
664
if (!Entry.isValid ())
726
665
return nullptr ;
727
666
0 commit comments