diff --git a/compiler-rt/lib/scudo/standalone/local_cache.h b/compiler-rt/lib/scudo/standalone/local_cache.h --- a/compiler-rt/lib/scudo/standalone/local_cache.h +++ b/compiler-rt/lib/scudo/standalone/local_cache.h @@ -159,6 +159,7 @@ DCHECK_GT(B->getCount(), 0); C->Count = B->getCount(); B->copyToArray(C->Chunks); + B->clear(); destroyBatch(ClassId, B); return true; } diff --git a/compiler-rt/lib/scudo/standalone/primary32.h b/compiler-rt/lib/scudo/standalone/primary32.h --- a/compiler-rt/lib/scudo/standalone/primary32.h +++ b/compiler-rt/lib/scudo/standalone/primary32.h @@ -444,6 +444,18 @@ if (BytesPushed < PageSize) return 0; // Nothing new to release. + // Releasing smaller blocks is expensive, so we want to make sure that a + // significant amount of bytes are free, and that there has been a good + // amount of batches pushed to the freelist before attempting to release. + if (BlockSize < PageSize / 16U) { + if (!Force && BytesPushed < Sci->AllocatedUser / 16U) + return 0; + // We want 8x% to 9x% free bytes (the larger the bock, the lower the %). + if ((BytesInFreeList * 100U) / Sci->AllocatedUser < + (100U - 1U - BlockSize / 16U)) + return 0; + } + if (!Force) { const s32 IntervalMs = getReleaseToOsIntervalMs(); if (IntervalMs < 0) diff --git a/compiler-rt/lib/scudo/standalone/primary64.h b/compiler-rt/lib/scudo/standalone/primary64.h --- a/compiler-rt/lib/scudo/standalone/primary64.h +++ b/compiler-rt/lib/scudo/standalone/primary64.h @@ -213,9 +213,7 @@ return reinterpret_cast(RegionInfoArray); } - static uptr getRegionInfoArraySize() { - return sizeof(RegionInfoArray); - } + static uptr getRegionInfoArraySize() { return sizeof(RegionInfoArray); } static BlockInfo findNearestBlock(const char *RegionInfoData, uptr Ptr) { const RegionInfo *RegionInfoArray = @@ -458,6 +456,18 @@ if (BytesPushed < PageSize) return 0; // Nothing new to release. + // Releasing smaller blocks is expensive, so we want to make sure that a + // significant amount of bytes are free, and that there has been a good + // amount of batches pushed to the freelist before attempting to release. + if (BlockSize < PageSize / 16U) { + if (!Force && BytesPushed < Region->AllocatedUser / 16U) + return 0; + // We want 8x% to 9x% free bytes (the larger the bock, the lower the %). + if ((BytesInFreeList * 100U) / Region->AllocatedUser < + (100U - 1U - BlockSize / 16U)) + return 0; + } + if (!Force) { const s32 IntervalMs = getReleaseToOsIntervalMs(); if (IntervalMs < 0) diff --git a/compiler-rt/lib/scudo/standalone/release.h b/compiler-rt/lib/scudo/standalone/release.h --- a/compiler-rt/lib/scudo/standalone/release.h +++ b/compiler-rt/lib/scudo/standalone/release.h @@ -69,7 +69,8 @@ BufferSize = (roundUpTo(N, static_cast(1U) << PackingRatioLog) >> PackingRatioLog) * sizeof(*Buffer); - if (BufferSize <= StaticBufferSize && Mutex.tryLock()) { + if (BufferSize <= (StaticBufferCount * sizeof(Buffer[0])) && + Mutex.tryLock()) { Buffer = &StaticBuffer[0]; memset(Buffer, 0, BufferSize); } else { @@ -114,6 +115,8 @@ uptr getBufferSize() const { return BufferSize; } + static const uptr StaticBufferCount = 1024U; + private: const uptr N; uptr CounterSizeBitsLog; @@ -125,8 +128,7 @@ uptr *Buffer; static HybridMutex Mutex; - static const uptr StaticBufferSize = 1024U; - static uptr StaticBuffer[StaticBufferSize]; + static uptr StaticBuffer[StaticBufferCount]; }; template class FreePagesRangeTracker { diff --git a/compiler-rt/lib/scudo/standalone/release.cpp b/compiler-rt/lib/scudo/standalone/release.cpp --- a/compiler-rt/lib/scudo/standalone/release.cpp +++ b/compiler-rt/lib/scudo/standalone/release.cpp @@ -11,6 +11,6 @@ namespace scudo { HybridMutex PackedCounterArray::Mutex = {}; -uptr PackedCounterArray::StaticBuffer[1024]; +uptr PackedCounterArray::StaticBuffer[PackedCounterArray::StaticBufferCount]; } // namespace scudo