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/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 @@ -86,9 +86,8 @@ // memory accesses which ends up being fairly costly. The current lower // limit is mostly arbitrary and based on empirical observations. // TODO(kostyak): make the lower limit a runtime option - Region->CanRelease = (I != SizeClassMap::BatchClassId) && - (getSizeByClassId(I) >= (PageSize / 32)); - if (Region->CanRelease) + Region->UseInterval = (getSizeByClassId(I) >= 128U); + if (Region->UseInterval) Region->ReleaseInfo.LastReleaseAtNs = Time; } setReleaseToOsIntervalMs(ReleaseToOsInterval); @@ -128,7 +127,7 @@ ScopedLock L(Region->Mutex); Region->FreeList.push_front(B); Region->Stats.PushedBlocks += B->getCount(); - if (Region->CanRelease) + if (ClassId != SizeClassMap::BatchClassId) releaseToOSMaybe(Region, ClassId); } @@ -287,7 +286,7 @@ HybridMutex Mutex; SinglyLinkedList FreeList; RegionStats Stats; - bool CanRelease; + bool UseInterval; bool Exhausted; u32 RandState; uptr RegionBeg; @@ -458,7 +457,18 @@ if (BytesPushed < PageSize) return 0; // Nothing new to release. + // Force a release if the number of bytes pushed since the last release and + // the number of bytes in the freelist are above given percentages of the + // allocated bytes for that class size, which usually indicates a burst in + // deallocation. + if (!Force && BytesPushed > (Region->AllocatedUser / 4U) && + (BytesInFreeList / (Region->AllocatedUser / 100U)) > + (100U - getMostSignificantSetBitIndex(BlockSize))) + Force = true; + if (!Force) { + if (!Region->UseInterval) + return 0; const s32 IntervalMs = getReleaseToOsIntervalMs(); if (IntervalMs < 0) return 0; @@ -474,12 +484,12 @@ Region->AllocatedUser, BlockSize, &Recorder); if (Recorder.getReleasedRangesCount() > 0) { - Region->ReleaseInfo.PushedBlocksAtLastRelease = - Region->Stats.PushedBlocks; Region->ReleaseInfo.RangesReleased += Recorder.getReleasedRangesCount(); Region->ReleaseInfo.LastReleasedBytes = Recorder.getReleasedBytes(); } - Region->ReleaseInfo.LastReleaseAtNs = getMonotonicTime(); + Region->ReleaseInfo.PushedBlocksAtLastRelease = Region->Stats.PushedBlocks; + if (Region->UseInterval) + Region->ReleaseInfo.LastReleaseAtNs = getMonotonicTime(); return Recorder.getReleasedBytes(); } };