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 (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 (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)