Commit e6ef5421 authored by Hannes Payer's avatar Hannes Payer Committed by Commit Bot

PartitionAlloc: PCScan: Perform scan only when quarantine is larger than the...

PartitionAlloc: PCScan: Perform scan only when quarantine is larger than the minimum scanning threshold.

This CL also another Reclaim mode to PartitionAllocMemoryReclaimer to force a scan when memory is critical.

Bug: 11297512
Change-Id: I054d8d032ed0b7e3abc9da57b33e6e471c830ed6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2550062
Commit-Queue: Hannes Payer <hpayer@chromium.org>
Reviewed-by: default avatarAnton Bikineev <bikineev@chromium.org>
Reviewed-by: default avatarMichael Lippautz <mlippautz@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#829663}
parent 8b83d018
......@@ -95,23 +95,34 @@ void PartitionAllocMemoryReclaimer::Start(
// singleton.
timer_->Start(
FROM_HERE, kInterval,
BindRepeating(&PartitionAllocMemoryReclaimer::Reclaim, Unretained(this)));
BindRepeating(&PartitionAllocMemoryReclaimer::ReclaimPeriodically,
Unretained(this)));
}
PartitionAllocMemoryReclaimer::PartitionAllocMemoryReclaimer() = default;
PartitionAllocMemoryReclaimer::~PartitionAllocMemoryReclaimer() = default;
void PartitionAllocMemoryReclaimer::Reclaim() {
AutoLock lock(lock_); // Has to protect from concurrent (Un)Register calls.
TRACE_EVENT0("base", "PartitionAllocMemoryReclaimer::Reclaim()");
void PartitionAllocMemoryReclaimer::ReclaimAll() {
constexpr int kFlags = PartitionPurgeDecommitEmptySlotSpans |
PartitionPurgeDiscardUnusedSystemPages |
PartitionPurgeForceAllFreed;
Reclaim(kFlags);
}
void PartitionAllocMemoryReclaimer::ReclaimPeriodically() {
constexpr int kFlags = PartitionPurgeDecommitEmptySlotSpans |
PartitionPurgeDiscardUnusedSystemPages;
Reclaim(kFlags);
}
void PartitionAllocMemoryReclaimer::Reclaim(int flags) {
AutoLock lock(lock_); // Has to protect from concurrent (Un)Register calls.
TRACE_EVENT0("base", "PartitionAllocMemoryReclaimer::Reclaim()");
for (auto* partition : thread_safe_partitions_)
partition->PurgeMemory(kFlags);
partition->PurgeMemory(flags);
for (auto* partition : thread_unsafe_partitions_)
partition->PurgeMemory(kFlags);
partition->PurgeMemory(flags);
}
void PartitionAllocMemoryReclaimer::ResetForTesting() {
......
......@@ -42,12 +42,17 @@ class BASE_EXPORT PartitionAllocMemoryReclaimer {
void UnregisterPartition(PartitionRoot<internal::NotThreadSafe>* partition);
// Starts the periodic reclaim. Should be called once.
void Start(scoped_refptr<SequencedTaskRunner> task_runner);
// Triggers an explicit reclaim now.
void Reclaim();
// Triggers an explicit reclaim now reclaiming all free memory
void ReclaimAll();
// Triggers an explicit reclaim now to reclaim as much free memory as
// possible.
void ReclaimPeriodically();
private:
PartitionAllocMemoryReclaimer();
~PartitionAllocMemoryReclaimer();
// |flags| is an OR of base::PartitionPurgeFlags
void Reclaim(int flags);
void ReclaimAndReschedule();
void ResetForTesting();
......
......@@ -98,7 +98,7 @@ TEST_F(PartitionAllocMemoryReclaimerTest, Reclaim) {
size_t committed_before = root->get_total_size_of_committed_pages();
EXPECT_GT(committed_before, committed_initially);
PartitionAllocMemoryReclaimer::Instance()->Reclaim();
PartitionAllocMemoryReclaimer::Instance()->ReclaimAll();
size_t committed_after = root->get_total_size_of_committed_pages();
EXPECT_LT(committed_after, committed_before);
......
......@@ -620,7 +620,7 @@ void* PartitionRoot<thread_safe>::ReallocFlags(int flags,
template <bool thread_safe>
void PartitionRoot<thread_safe>::PurgeMemory(int flags) {
// TODO(chromium:1129751): Change to LIKELY once PCScan is enabled by default.
if (UNLIKELY(pcscan)) {
if (UNLIKELY(pcscan) && (flags & PartitionPurgeForceAllFreed)) {
pcscan->PerformScanIfNeeded(
internal::PCScan<thread_safe>::InvocationMode::kBlocking);
}
......
......@@ -78,6 +78,8 @@ enum PartitionPurgeFlags {
// size. It often frees a similar amount of memory to decommitting the empty
// slot spans, though.
PartitionPurgeDiscardUnusedSystemPages = 1 << 1,
// Free calls which have not been marterialized are forced now.
PartitionPurgeForceAllFreed = 1 << 2,
};
// Options struct used to configure PartitionRoot and PartitionAllocator.
......
......@@ -486,8 +486,7 @@ void PCScan<thread_safe>::PerformScan(InvocationMode invocation_mode) {
template <bool thread_safe>
void PCScan<thread_safe>::PerformScanIfNeeded(InvocationMode invocation_mode) {
// Perform PCScan only if quarantine is not empty.
if (quarantine_data_.size())
if (quarantine_data_.MinimumScanningThresholdReached())
PerformScan(invocation_mode);
}
......
......@@ -73,6 +73,10 @@ class BASE_EXPORT PCScan final {
}
size_t last_size() const { return last_size_; }
bool MinimumScanningThresholdReached() const {
return size() > kQuarantineSizeMinLimit;
}
private:
static constexpr size_t kQuarantineSizeMinLimit = 1 * 1024 * 1024;
......
......@@ -29,7 +29,7 @@ namespace blink {
// Function defined in third_party/blink/public/web/blink.h.
void DecommitFreeableMemory() {
CHECK(IsMainThread());
base::PartitionAllocMemoryReclaimer::Instance()->Reclaim();
base::PartitionAllocMemoryReclaimer::Instance()->ReclaimAll();
}
// static
......@@ -106,7 +106,7 @@ void MemoryPressureListenerRegistry::OnMemoryPressure(
CHECK(IsMainThread());
for (auto& client : clients_)
client->OnMemoryPressure(level);
base::PartitionAllocMemoryReclaimer::Instance()->Reclaim();
base::PartitionAllocMemoryReclaimer::Instance()->ReclaimAll();
}
void MemoryPressureListenerRegistry::OnPurgeMemory() {
......@@ -114,7 +114,7 @@ void MemoryPressureListenerRegistry::OnPurgeMemory() {
for (auto& client : clients_)
client->OnPurgeMemory();
ImageDecodingStore::Instance().Clear();
base::PartitionAllocMemoryReclaimer::Instance()->Reclaim();
base::PartitionAllocMemoryReclaimer::Instance()->ReclaimAll();
// Thread-specific data never issues a layout, so we are safe here.
MutexLocker lock(threads_mutex_);
......
......@@ -19,7 +19,7 @@ namespace WTF {
class PartitionsTest : public ::testing::Test {
protected:
void TearDown() override {
base::PartitionAllocMemoryReclaimer::Instance()->Reclaim();
base::PartitionAllocMemoryReclaimer::Instance()->ReclaimAll();
}
};
......@@ -68,7 +68,7 @@ TEST_F(PartitionsTest, Decommit) {
// Decommit is not triggered by deallocation.
EXPECT_GT(committed_after, committed_before);
// Decommit works.
base::PartitionAllocMemoryReclaimer::Instance()->Reclaim();
base::PartitionAllocMemoryReclaimer::Instance()->ReclaimAll();
EXPECT_LT(Partitions::TotalSizeOfCommittedPages(), committed_after);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment