Commit 24b7eccf authored by Anton Bikineev's avatar Anton Bikineev Committed by Chromium LUCI CQ

PCScan: Avoid repeating scans and cache purging while reclaiming

PCScan (and cache purging) was redundantly performed for each
partition root. This CL moves these routines out of the root loops.

Change-Id: I42eabeb024126100c47b7c757121aa5b969d4493
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2610588
Commit-Queue: Anton Bikineev <bikineev@chromium.org>
Reviewed-by: default avatarBenoit L <lizeb@chromium.org>
Reviewed-by: default avatarBartek Nowierski <bartekn@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#840941}
parent d7df01a3
......@@ -6,6 +6,7 @@
#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/allocator/partition_allocator/partition_alloc_check.h"
#include "base/allocator/partition_allocator/pcscan.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
......@@ -119,6 +120,27 @@ void PartitionAllocMemoryReclaimer::Reclaim(int flags) {
AutoLock lock(lock_); // Has to protect from concurrent (Un)Register calls.
TRACE_EVENT0("base", "PartitionAllocMemoryReclaimer::Reclaim()");
// PCScan quarantines freed slots. Trigger the scan first to let it call
// FreeNoHooksImmediate on slots that pass the quarantine.
//
// In turn, FreeNoHooksImmediate may add slots to thread cache. Purge it next
// so that the slots are actually freed. (This is done synchronously only for
// the current thread.)
//
// Lastly decommit empty slot spans and lastly try to discard unused pages at
// the end of the remaining active slots.
{
using PCScan = internal::PCScan<internal::ThreadSafe>;
const auto invocation_mode = flags & PartitionPurgeForceAllFreed
? PCScan::InvocationMode::kForcedBlocking
: PCScan::InvocationMode::kBlocking;
PCScan::Instance().PerformScanIfNeeded(invocation_mode);
}
#if defined(PA_THREAD_CACHE_SUPPORTED)
internal::ThreadCacheRegistry::Instance().PurgeAll();
#endif
for (auto* partition : thread_safe_partitions_)
partition->PurgeMemory(flags);
for (auto* partition : thread_unsafe_partitions_)
......
......@@ -636,27 +636,6 @@ void* PartitionRoot<thread_safe>::ReallocFlags(int flags,
template <bool thread_safe>
void PartitionRoot<thread_safe>::PurgeMemory(int flags) {
// PCScan quarantines freed slots. Trigger the scan first to let it call
// FreeNoHooksImmediate on slots that pass the quarantine.
//
// In turn, FreeNoHooksImmediate may add slots to thread cache. Purge it next
// so that the slots are actually freed. (This is done synchronously only for
// the current thread.)
//
// Lastly decommit empty slot spans and lastly try to discard unused pages at
// the end of the remaining active slots.
// TODO(chromium:1129751): Change to LIKELY once PCScan is enabled by default.
if (UNLIKELY(IsScanEnabled())) {
if (flags & PartitionPurgeForceAllFreed)
PCScan::Instance().PerformScan(PCScan::InvocationMode::kBlocking);
else
PCScan::Instance().PerformScanIfNeeded(PCScan::InvocationMode::kBlocking);
}
if (with_thread_cache)
internal::ThreadCacheRegistry::Instance().PurgeAll();
{
ScopedGuard guard{lock_};
// Avoid purging if there is PCScan task currently scheduled. Since pcscan
......
......@@ -556,14 +556,18 @@ void PCScan<thread_safe>::PerformScan(InvocationMode invocation_mode) {
if (LIKELY(invocation_mode == InvocationMode::kNonBlocking)) {
PCScanThread::Instance().PostTask(std::move(task));
} else {
PA_DCHECK(InvocationMode::kBlocking == invocation_mode);
PA_DCHECK(InvocationMode::kBlocking == invocation_mode ||
InvocationMode::kForcedBlocking == invocation_mode);
std::move(*task).RunOnce();
}
}
template <bool thread_safe>
void PCScan<thread_safe>::PerformScanIfNeeded(InvocationMode invocation_mode) {
if (quarantine_data_.MinimumScanningThresholdReached())
if (!roots_.size())
return;
if (invocation_mode == InvocationMode::kForcedBlocking ||
quarantine_data_.MinimumScanningThresholdReached())
PerformScan(invocation_mode);
}
......
......@@ -47,6 +47,7 @@ class BASE_EXPORT PCScan final {
enum class InvocationMode {
kBlocking,
kNonBlocking,
kForcedBlocking,
};
static PCScan& Instance() {
......@@ -66,8 +67,6 @@ class BASE_EXPORT PCScan final {
ALWAYS_INLINE void MoveToQuarantine(void* ptr, SlotSpan* slot_span);
// Performs scanning unconditionally.
void PerformScan(InvocationMode invocation_mode);
// Performs scanning only if a certain quarantine threshold was reached.
void PerformScanIfNeeded(InvocationMode invocation_mode);
......@@ -142,6 +141,9 @@ class BASE_EXPORT PCScan final {
constexpr PCScan() = default;
// Performs scanning unconditionally.
void PerformScan(InvocationMode invocation_mode);
static PCScan instance_ PA_CONSTINIT;
Roots roots_{};
......
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