Commit 5548808f authored by Sebastien Marchand's avatar Sebastien Marchand Committed by Commit Bot

[PM] High PM policy: discard tabs directly

This updates the High PM policy to make it discard tabs directly rather
than sending memory pressure signals.

Change-Id: I26c85179b8c03268d84c0c99918239f2344bb6d3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2304106
Commit-Queue: Sébastien Marchand <sebmarchand@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790908}
parent b790cc7a
...@@ -1073,8 +1073,6 @@ static_library("browser") { ...@@ -1073,8 +1073,6 @@ static_library("browser") {
"performance_manager/decorators/process_metrics_decorator.h", "performance_manager/decorators/process_metrics_decorator.h",
"performance_manager/decorators/process_priority_aggregator.cc", "performance_manager/decorators/process_priority_aggregator.cc",
"performance_manager/decorators/process_priority_aggregator.h", "performance_manager/decorators/process_priority_aggregator.h",
"performance_manager/mechanisms/high_pmf_memory_pressure_signals.cc",
"performance_manager/mechanisms/high_pmf_memory_pressure_signals.h",
"performance_manager/mechanisms/working_set_trimmer.cc", "performance_manager/mechanisms/working_set_trimmer.cc",
"performance_manager/mechanisms/working_set_trimmer.h", "performance_manager/mechanisms/working_set_trimmer.h",
"performance_manager/metrics/memory_pressure_metrics.cc", "performance_manager/metrics/memory_pressure_metrics.cc",
...@@ -1084,8 +1082,6 @@ static_library("browser") { ...@@ -1084,8 +1082,6 @@ static_library("browser") {
"performance_manager/observers/isolation_context_metrics.h", "performance_manager/observers/isolation_context_metrics.h",
"performance_manager/observers/metrics_collector.cc", "performance_manager/observers/metrics_collector.cc",
"performance_manager/observers/metrics_collector.h", "performance_manager/observers/metrics_collector.h",
"performance_manager/policies/high_pmf_memory_pressure_policy.cc",
"performance_manager/policies/high_pmf_memory_pressure_policy.h",
"performance_manager/policies/policy_features.cc", "performance_manager/policies/policy_features.cc",
"performance_manager/policies/policy_features.h", "performance_manager/policies/policy_features.h",
"performance_manager/policies/working_set_trimmer_policy.cc", "performance_manager/policies/working_set_trimmer_policy.cc",
...@@ -3363,6 +3359,8 @@ static_library("browser") { ...@@ -3363,6 +3359,8 @@ static_library("browser") {
"performance_manager/policies/background_tab_loading_policy.h", "performance_manager/policies/background_tab_loading_policy.h",
"performance_manager/policies/background_tab_loading_policy_helpers.cc", "performance_manager/policies/background_tab_loading_policy_helpers.cc",
"performance_manager/policies/background_tab_loading_policy_helpers.h", "performance_manager/policies/background_tab_loading_policy_helpers.h",
"performance_manager/policies/high_pmf_discard_policy.cc",
"performance_manager/policies/high_pmf_discard_policy.h",
"performance_manager/policies/page_discarding_helper.cc", "performance_manager/policies/page_discarding_helper.cc",
"performance_manager/policies/page_discarding_helper.h", "performance_manager/policies/page_discarding_helper.h",
"performance_manager/policies/urgent_page_discarding_policy.cc", "performance_manager/policies/urgent_page_discarding_policy.cc",
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
#include "chrome/browser/performance_manager/observers/isolation_context_metrics.h" #include "chrome/browser/performance_manager/observers/isolation_context_metrics.h"
#include "chrome/browser/performance_manager/observers/metrics_collector.h" #include "chrome/browser/performance_manager/observers/metrics_collector.h"
#include "chrome/browser/performance_manager/policies/background_tab_loading_policy.h" #include "chrome/browser/performance_manager/policies/background_tab_loading_policy.h"
#include "chrome/browser/performance_manager/policies/high_pmf_memory_pressure_policy.h" #include "chrome/browser/performance_manager/policies/high_pmf_discard_policy.h"
#include "chrome/browser/performance_manager/policies/policy_features.h" #include "chrome/browser/performance_manager/policies/policy_features.h"
#include "chrome/browser/performance_manager/policies/working_set_trimmer_policy.h" #include "chrome/browser/performance_manager/policies/working_set_trimmer_policy.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
...@@ -120,18 +120,17 @@ void ChromeBrowserMainExtraPartsPerformanceManager::CreatePoliciesAndDecorators( ...@@ -120,18 +120,17 @@ void ChromeBrowserMainExtraPartsPerformanceManager::CreatePoliciesAndDecorators(
std::make_unique< std::make_unique<
performance_manager::policies::BackgroundTabLoadingPolicy>()); performance_manager::policies::BackgroundTabLoadingPolicy>());
} }
if (base::FeatureList::IsEnabled(
performance_manager::features::kHighPMFDiscardPolicy)) {
graph->PassToGraph(std::make_unique<
performance_manager::policies::HighPMFDiscardPolicy>());
}
#endif // !defined(OS_ANDROID) #endif // !defined(OS_ANDROID)
graph->PassToGraph( graph->PassToGraph(
std::make_unique<performance_manager::metrics::MemoryPressureMetrics>()); std::make_unique<performance_manager::metrics::MemoryPressureMetrics>());
if (base::FeatureList::IsEnabled(
performance_manager::features::kHighPMFMemoryPressureSignals)) {
graph->PassToGraph(
std::make_unique<
performance_manager::policies::HighPMFMemoryPressurePolicy>());
}
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
performance_manager::features::kTabLoadingFrameNavigationThrottles)) { performance_manager::features::kTabLoadingFrameNavigationThrottles)) {
graph->PassToGraph( graph->PassToGraph(
......
...@@ -49,12 +49,12 @@ void ProcessMetricsDecorator::StartTimer() { ...@@ -49,12 +49,12 @@ void ProcessMetricsDecorator::StartTimer() {
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
// Bump the refresh frequency when urgent discarding is done from the graph or // Bump the refresh frequency when urgent discarding is done from the graph or
// when emitting memory pressure signals on high PMF as these features relies // when discarding tabs on high PMF as these features relies on relatively
// on relatively fresh data. // fresh data.
// TODO(sebmarchand): Measure the performance impact of this. // TODO(sebmarchand): Measure the performance impact of this.
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
features::kUrgentDiscardingFromPerformanceManager) || features::kUrgentDiscardingFromPerformanceManager) ||
base::FeatureList::IsEnabled(features::kHighPMFMemoryPressureSignals)) { base::FeatureList::IsEnabled(features::kHighPMFDiscardPolicy)) {
refresh_period = kFastRefreshTimerPeriod; refresh_period = kFastRefreshTimerPeriod;
} }
#endif #endif
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/performance_manager/mechanisms/high_pmf_memory_pressure_signals.h"
#include <memory>
#include "base/bind.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/util/memory_pressure/memory_pressure_voter.h"
#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
namespace performance_manager {
namespace mechanism {
// Wrapper around a MemoryPressureVoter living on the UI thread.
class MemoryPressureVoterOnUIThread {
public:
MemoryPressureVoterOnUIThread() = default;
virtual ~MemoryPressureVoterOnUIThread() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
}
MemoryPressureVoterOnUIThread(const MemoryPressureVoterOnUIThread& other) =
delete;
MemoryPressureVoterOnUIThread& operator=(
const MemoryPressureVoterOnUIThread&) = delete;
void InitOnUIThread() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
voter_ = static_cast<util::MultiSourceMemoryPressureMonitor*>(
base::MemoryPressureMonitor::Get())
->CreateVoter();
}
void SetVote(base::MemoryPressureListener::MemoryPressureLevel level,
bool notify) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
voter_->SetVote(level, notify);
}
private:
std::unique_ptr<util::MemoryPressureVoter> voter_;
};
HighPMFMemoryPressureSignals::HighPMFMemoryPressureSignals() {
ui_thread_voter_ = std::make_unique<MemoryPressureVoterOnUIThread>();
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&MemoryPressureVoterOnUIThread::InitOnUIThread,
base::Unretained(ui_thread_voter_.get())));
}
HighPMFMemoryPressureSignals::~HighPMFMemoryPressureSignals() {
content::GetUIThreadTaskRunner({})->DeleteSoon(FROM_HERE,
std::move(ui_thread_voter_));
}
void HighPMFMemoryPressureSignals::SetPressureLevel(MemoryPressureLevel level) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool notify = level == MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL;
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&MemoryPressureVoterOnUIThread::SetVote,
base::Unretained(ui_thread_voter_.get()), level, notify));
pressure_level_ = level;
}
} // namespace mechanism
} // namespace performance_manager
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_MECHANISMS_HIGH_PMF_MEMORY_PRESSURE_SIGNALS_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_MECHANISMS_HIGH_PMF_MEMORY_PRESSURE_SIGNALS_H_
#include "base/memory/memory_pressure_listener.h"
#include "base/sequence_checker.h"
namespace performance_manager {
namespace mechanism {
class MemoryPressureVoterOnUIThread;
// HighPMFMemoryPressureSignals is meant to be used by a
// HighPMFMemoryPressurePolicy to notify the global MemoryPressureMonitor when
// the total PMF of Chrome exceeds a threshold.
class HighPMFMemoryPressureSignals {
public:
using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel;
HighPMFMemoryPressureSignals();
~HighPMFMemoryPressureSignals();
HighPMFMemoryPressureSignals(const HighPMFMemoryPressureSignals& other) =
delete;
HighPMFMemoryPressureSignals& operator=(const HighPMFMemoryPressureSignals&) =
delete;
// Should be called each time the memory pressure level computed by
// HighPMFMemoryPressurePolicy changes.
void SetPressureLevel(MemoryPressureLevel level);
private:
MemoryPressureLevel pressure_level_ =
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE;
std::unique_ptr<MemoryPressureVoterOnUIThread> ui_thread_voter_;
SEQUENCE_CHECKER(sequence_checker_);
};
} // namespace mechanism
} // namespace performance_manager
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_MECHANISMS_HIGH_PMF_MEMORY_PRESSURE_SIGNALS_H_
...@@ -2,13 +2,12 @@ ...@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/performance_manager/policies/high_pmf_memory_pressure_policy.h" #include "chrome/browser/performance_manager/policies/high_pmf_discard_policy.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/metrics/field_trial_params.h" #include "base/metrics/field_trial_params.h"
#include "base/process/process_metrics.h" #include "base/process/process_metrics.h"
#include "chrome/browser/performance_manager/mechanisms/high_pmf_memory_pressure_signals.h" #include "chrome/browser/performance_manager/policies/page_discarding_helper.h"
#include "chrome/browser/performance_manager/policies/policy_features.h" #include "chrome/browser/performance_manager/policies/policy_features.h"
#include "components/performance_manager/public/graph/process_node.h" #include "components/performance_manager/public/graph/process_node.h"
...@@ -20,15 +19,20 @@ namespace { ...@@ -20,15 +19,20 @@ namespace {
// The factor that will be applied to the total amount of RAM to establish the // The factor that will be applied to the total amount of RAM to establish the
// PMF limit. // PMF limit.
static constexpr base::FeatureParam<double> kRAMRatioPMFLimitFactor{ static constexpr base::FeatureParam<double> kRAMRatioPMFLimitFactor{
&performance_manager::features::kHighPMFMemoryPressureSignals, &performance_manager::features::kHighPMFDiscardPolicy,
"RAMRatioPMFLimitFactor", 1.5}; "RAMRatioPMFLimitFactor", 1.5};
// The discard strategy to use.
static constexpr base::FeatureParam<int> kDiscardStrategy{
&performance_manager::features::kHighPMFDiscardPolicy, "DiscardStrategy",
static_cast<int>(features::DiscardStrategy::LRU)};
} // namespace } // namespace
HighPMFMemoryPressurePolicy::HighPMFMemoryPressurePolicy() = default; HighPMFDiscardPolicy::HighPMFDiscardPolicy() = default;
HighPMFMemoryPressurePolicy::~HighPMFMemoryPressurePolicy() = default; HighPMFDiscardPolicy::~HighPMFDiscardPolicy() = default;
void HighPMFMemoryPressurePolicy::OnPassedToGraph(Graph* graph) { void HighPMFDiscardPolicy::OnPassedToGraph(Graph* graph) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
graph->AddSystemNodeObserver(this); graph->AddSystemNodeObserver(this);
graph_ = graph; graph_ = graph;
...@@ -37,37 +41,51 @@ void HighPMFMemoryPressurePolicy::OnPassedToGraph(Graph* graph) { ...@@ -37,37 +41,51 @@ void HighPMFMemoryPressurePolicy::OnPassedToGraph(Graph* graph) {
if (base::GetSystemMemoryInfo(&mem_info)) if (base::GetSystemMemoryInfo(&mem_info))
pmf_limit_kb_ = mem_info.total * kRAMRatioPMFLimitFactor.Get(); pmf_limit_kb_ = mem_info.total * kRAMRatioPMFLimitFactor.Get();
mechanism_ = std::make_unique<mechanism::HighPMFMemoryPressureSignals>(); DCHECK(PageDiscardingHelper::GetFromGraph(graph_))
<< "A PageDiscardingHelper instance should be registered against the "
"graph in order to use this policy.";
} }
void HighPMFMemoryPressurePolicy::OnTakenFromGraph(Graph* graph) { void HighPMFDiscardPolicy::OnTakenFromGraph(Graph* graph) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
graph->RemoveSystemNodeObserver(this); graph->RemoveSystemNodeObserver(this);
graph_ = nullptr; graph_ = nullptr;
pmf_limit_kb_ = kInvalidPMFLimitValue; pmf_limit_kb_ = kInvalidPMFLimitValue;
mechanism_.reset();
} }
void HighPMFMemoryPressurePolicy::OnProcessMemoryMetricsAvailable( void HighPMFDiscardPolicy::OnProcessMemoryMetricsAvailable(
const SystemNode* unused) { const SystemNode* unused) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (pmf_limit_kb_ == kInvalidPMFLimitValue) if (pmf_limit_kb_ == kInvalidPMFLimitValue)
return; return;
if (discard_attempt_in_progress_)
return;
int total_pmf_kb = 0; int total_pmf_kb = 0;
MemoryPressureLevel pressure_level = bool should_discard = false;
MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE;
auto process_nodes = graph_->GetAllProcessNodes(); auto process_nodes = graph_->GetAllProcessNodes();
for (const auto* node : process_nodes) { for (const auto* node : process_nodes) {
total_pmf_kb += node->GetPrivateFootprintKb(); total_pmf_kb += node->GetPrivateFootprintKb();
if (total_pmf_kb >= pmf_limit_kb_) { if (total_pmf_kb >= pmf_limit_kb_) {
pressure_level = MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL; should_discard = true;
break; break;
} }
} }
mechanism_->SetPressureLevel(pressure_level); if (should_discard) {
discard_attempt_in_progress_ = true;
PageDiscardingHelper::GetFromGraph(graph_)->UrgentlyDiscardAPage(
static_cast<features::DiscardStrategy>(kDiscardStrategy.Get()),
base::BindOnce(&HighPMFDiscardPolicy::PostDiscardAttemptCallback,
base::Unretained(this)));
}
}
void HighPMFDiscardPolicy::PostDiscardAttemptCallback(bool success) {
DCHECK(discard_attempt_in_progress_);
discard_attempt_in_progress_ = false;
} }
} // namespace policies } // namespace policies
......
...@@ -2,10 +2,9 @@ ...@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_HIGH_PMF_MEMORY_PRESSURE_POLICY_H_ #ifndef CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_HIGH_PMF_DISCARD_POLICY_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_HIGH_PMF_MEMORY_PRESSURE_POLICY_H_ #define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_HIGH_PMF_DISCARD_POLICY_H_
#include "base/memory/memory_pressure_listener.h"
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "components/performance_manager/public/graph/graph.h" #include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/system_node.h" #include "components/performance_manager/public/graph/system_node.h"
...@@ -14,23 +13,17 @@ namespace performance_manager { ...@@ -14,23 +13,17 @@ namespace performance_manager {
class Graph; class Graph;
namespace mechanism {
class HighPMFMemoryPressureSignals;
}
namespace policies { namespace policies {
// The HighPMFMemoryPressurePolicy will emit critical memory pressure signal // The HighPMFDiscardPolicy will discard tabs when Chrome's total PMF exceeds a
// when Chrome's total PMF exceeds a given threshold. // given threshold.
class HighPMFMemoryPressurePolicy : public GraphOwned, class HighPMFDiscardPolicy : public GraphOwned,
public SystemNode::ObserverDefaultImpl { public SystemNode::ObserverDefaultImpl {
public: public:
HighPMFMemoryPressurePolicy(); HighPMFDiscardPolicy();
~HighPMFMemoryPressurePolicy() override; ~HighPMFDiscardPolicy() override;
HighPMFMemoryPressurePolicy(const HighPMFMemoryPressurePolicy& other) = HighPMFDiscardPolicy(const HighPMFDiscardPolicy& other) = delete;
delete; HighPMFDiscardPolicy& operator=(const HighPMFDiscardPolicy&) = delete;
HighPMFMemoryPressurePolicy& operator=(const HighPMFMemoryPressurePolicy&) =
delete;
// GraphOwned implementation: // GraphOwned implementation:
void OnPassedToGraph(Graph* graph) override; void OnPassedToGraph(Graph* graph) override;
...@@ -44,18 +37,23 @@ class HighPMFMemoryPressurePolicy : public GraphOwned, ...@@ -44,18 +37,23 @@ class HighPMFMemoryPressurePolicy : public GraphOwned,
} }
private: private:
using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; // Callback called when a discard attempt has completed.
void PostDiscardAttemptCallback(bool success);
const int kInvalidPMFLimitValue = 0; const int kInvalidPMFLimitValue = 0;
int pmf_limit_kb_ = kInvalidPMFLimitValue; int pmf_limit_kb_ = kInvalidPMFLimitValue;
std::unique_ptr<mechanism::HighPMFMemoryPressureSignals> mechanism_;
Graph* graph_ = nullptr; Graph* graph_ = nullptr;
// Indicates whether or not there's a discard attempt in progress. This could
// happen if this attempt doesn't complete between 2 calls to
// OnProcessMemoryMetricsAvailable.
bool discard_attempt_in_progress_ = false;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
}; };
} // namespace policies } // namespace policies
} // namespace performance_manager } // namespace performance_manager
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_HIGH_PMF_MEMORY_PRESSURE_POLICY_H_ #endif // CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_HIGH_PMF_DISCARD_POLICY_H_
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/performance_manager/policies/high_pmf_discard_policy.h"
#include "base/bind.h"
#include "chrome/browser/performance_manager/test_support/page_discarding_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace performance_manager {
namespace policies {
using HighPMFDiscardPolicyTest = testing::GraphTestHarnessWithMockDiscarder;
TEST_F(HighPMFDiscardPolicyTest, EndToEnd) {
// Create the policy and pass it to the graph.
auto policy = std::make_unique<HighPMFDiscardPolicy>();
auto* policy_raw = policy.get();
graph()->PassToGraph(std::move(policy));
const int kPMFLimitKb = 100 * 1024;
policy_raw->set_pmf_limit_for_testing(kPMFLimitKb);
auto process_node = CreateNode<performance_manager::ProcessNodeImpl>();
process_node->set_private_footprint_kb(kPMFLimitKb - 1);
graph()->FindOrCreateSystemNodeImpl()->OnProcessMemoryMetricsAvailable();
// Make sure that no task get posted to the discarder.
task_env().RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(discarder());
process_node->set_private_footprint_kb(kPMFLimitKb);
EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node()))
.WillOnce(::testing::Return(true));
graph()->FindOrCreateSystemNodeImpl()->OnProcessMemoryMetricsAvailable();
task_env().RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(discarder());
graph()->TakeFromGraph(policy_raw);
}
} // namespace policies
} // namespace performance_manager
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/performance_manager/policies/high_pmf_memory_pressure_policy.h"
#include "base/bind.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h"
#include "components/performance_manager/graph/graph_impl.h"
#include "components/performance_manager/test_support/graph_test_harness.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace performance_manager {
namespace policies {
using HighPMFMemoryPressurePolicyTest = GraphTestHarness;
TEST_F(HighPMFMemoryPressurePolicyTest, EndToEnd) {
// Create the policy and pass it to the graph.
auto policy = std::make_unique<HighPMFMemoryPressurePolicy>();
auto* policy_raw = policy.get();
graph()->PassToGraph(std::move(policy));
const int kPMFLimitKb = 100 * 1024;
policy_raw->set_pmf_limit_for_testing(kPMFLimitKb);
// Create a MemoryPressureListener object that will record that a critical
// memory pressure signal has been emitted.
base::RunLoop run_loop;
auto quit_closure = run_loop.QuitClosure();
bool memory_pressure_listener_called = false;
util::MultiSourceMemoryPressureMonitor memory_pressure_monitor;
base::MemoryPressureListener memory_pressure_listener(
FROM_HERE,
base::BindLambdaForTesting(
[&](base::MemoryPressureListener::MemoryPressureLevel level) {
EXPECT_EQ(base::MemoryPressureListener::MemoryPressureLevel::
MEMORY_PRESSURE_LEVEL_CRITICAL,
level);
memory_pressure_listener_called = true;
quit_closure.Run();
}));
auto process_node = CreateNode<performance_manager::ProcessNodeImpl>();
process_node->set_private_footprint_kb(kPMFLimitKb - 1);
graph()->FindOrCreateSystemNodeImpl()->OnProcessMemoryMetricsAvailable();
// Make sure that no task get posted to the memory pressure monitor to record
// a memory pressure event.
task_env().RunUntilIdle();
EXPECT_FALSE(memory_pressure_listener_called);
EXPECT_EQ(base::MemoryPressureListener::MemoryPressureLevel::
MEMORY_PRESSURE_LEVEL_NONE,
memory_pressure_monitor.GetCurrentPressureLevel());
process_node->set_private_footprint_kb(kPMFLimitKb);
graph()->FindOrCreateSystemNodeImpl()->OnProcessMemoryMetricsAvailable();
// Wait for the MemoryPressureListener to be called.
run_loop.Run();
EXPECT_TRUE(memory_pressure_listener_called);
EXPECT_EQ(base::MemoryPressureListener::MemoryPressureLevel::
MEMORY_PRESSURE_LEVEL_CRITICAL,
memory_pressure_monitor.GetCurrentPressureLevel());
memory_pressure_listener_called = false;
process_node->set_private_footprint_kb(kPMFLimitKb - 1);
graph()->FindOrCreateSystemNodeImpl()->OnProcessMemoryMetricsAvailable();
// Make sure that the pressure level goes back to NONE.
task_env().RunUntilIdle();
EXPECT_FALSE(memory_pressure_listener_called);
EXPECT_EQ(base::MemoryPressureListener::MemoryPressureLevel::
MEMORY_PRESSURE_LEVEL_NONE,
memory_pressure_monitor.GetCurrentPressureLevel());
graph()->TakeFromGraph(policy_raw);
// The policy's voter post a task to the UI thread on destruction, wait for
// this to complete.
task_env().RunUntilIdle();
}
} // namespace policies
} // namespace performance_manager
...@@ -64,7 +64,7 @@ PageDiscardingHelper::PageDiscardingHelper() ...@@ -64,7 +64,7 @@ PageDiscardingHelper::PageDiscardingHelper()
PageDiscardingHelper::~PageDiscardingHelper() = default; PageDiscardingHelper::~PageDiscardingHelper() = default;
void PageDiscardingHelper::UrgentlyDiscardAPage( void PageDiscardingHelper::UrgentlyDiscardAPage(
features::UrgentDiscardingParams::DiscardStrategy discard_strategy, features::DiscardStrategy discard_strategy,
base::OnceCallback<void(bool)> post_discard_cb) { base::OnceCallback<void(bool)> post_discard_cb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
...@@ -93,11 +93,9 @@ void PageDiscardingHelper::UrgentlyDiscardAPage( ...@@ -93,11 +93,9 @@ void PageDiscardingHelper::UrgentlyDiscardAPage(
return; return;
} }
if (discard_strategy == if (discard_strategy == features::DiscardStrategy::LRU) {
features::UrgentDiscardingParams::DiscardStrategy::LRU) {
discard_candidate = oldest_bg_discardable_page_node; discard_candidate = oldest_bg_discardable_page_node;
} else if (discard_strategy == } else if (discard_strategy == features::DiscardStrategy::BIGGEST_RSS) {
features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS) {
// List all the processes associated with these page nodes. // List all the processes associated with these page nodes.
base::flat_set<const ProcessNode*> process_nodes; base::flat_set<const ProcessNode*> process_nodes;
for (const auto& iter : discardable_pages) { for (const auto& iter : discardable_pages) {
...@@ -301,7 +299,7 @@ base::Value PageDiscardingHelper::DescribePageNodeData( ...@@ -301,7 +299,7 @@ base::Value PageDiscardingHelper::DescribePageNodeData(
} }
void PageDiscardingHelper::PostDiscardAttemptCallback( void PageDiscardingHelper::PostDiscardAttemptCallback(
features::UrgentDiscardingParams::DiscardStrategy discard_strategy, features::DiscardStrategy discard_strategy,
base::OnceCallback<void(bool)> post_discard_cb, base::OnceCallback<void(bool)> post_discard_cb,
bool success) { bool success) {
if (!success) { if (!success) {
......
...@@ -41,8 +41,7 @@ class PageDiscardingHelper : public GraphOwned, ...@@ -41,8 +41,7 @@ class PageDiscardingHelper : public GraphOwned,
// Selects a tab to discard based on |strategy| and posts to the UI thread to // Selects a tab to discard based on |strategy| and posts to the UI thread to
// discard it. This will try to discard a tab until there's been a successful // discard it. This will try to discard a tab until there's been a successful
// discard or until there's no more discard candidate. // discard or until there's no more discard candidate.
void UrgentlyDiscardAPage( void UrgentlyDiscardAPage(features::DiscardStrategy discard_strategy,
features::UrgentDiscardingParams::DiscardStrategy discard_strategy,
base::OnceCallback<void(bool)> post_discard_cb); base::OnceCallback<void(bool)> post_discard_cb);
// PageNodeObserver: // PageNodeObserver:
...@@ -77,7 +76,7 @@ class PageDiscardingHelper : public GraphOwned, ...@@ -77,7 +76,7 @@ class PageDiscardingHelper : public GraphOwned,
// the attempt has been successful. |post_discard_cb| will be called once // the attempt has been successful. |post_discard_cb| will be called once
// there's been a successful discard or if there's no more discard candidates. // there's been a successful discard or if there's no more discard candidates.
void PostDiscardAttemptCallback( void PostDiscardAttemptCallback(
features::UrgentDiscardingParams::DiscardStrategy discard_strategy, features::DiscardStrategy discard_strategy,
base::OnceCallback<void(bool)> post_discard_cb, base::OnceCallback<void(bool)> post_discard_cb,
bool success); bool success);
......
...@@ -192,8 +192,7 @@ TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageWithFormInteractions) { ...@@ -192,8 +192,7 @@ TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageWithFormInteractions) {
class ParameterizedPageDiscardingHelperTest class ParameterizedPageDiscardingHelperTest
: public PageDiscardingHelperTest, : public PageDiscardingHelperTest,
public ::testing::WithParamInterface< public ::testing::WithParamInterface<features::DiscardStrategy> {
features::UrgentDiscardingParams::DiscardStrategy> {
public: public:
ParameterizedPageDiscardingHelperTest() = default; ParameterizedPageDiscardingHelperTest() = default;
~ParameterizedPageDiscardingHelperTest() override = default; ~ParameterizedPageDiscardingHelperTest() override = default;
...@@ -261,8 +260,7 @@ TEST_P(ParameterizedPageDiscardingHelperTest, ...@@ -261,8 +260,7 @@ TEST_P(ParameterizedPageDiscardingHelperTest,
process_node()->set_resident_set_kb(1024); process_node()->set_resident_set_kb(1024);
process_node2->set_resident_set_kb(2048); process_node2->set_resident_set_kb(2048);
if (GetParam() == if (GetParam() == features::DiscardStrategy::BIGGEST_RSS) {
features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS) {
// |page_node2| should be discarded despite being the most recently visible // |page_node2| should be discarded despite being the most recently visible
// page as it has a bigger footprint. // page as it has a bigger footprint.
EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get())) EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get()))
...@@ -301,8 +299,7 @@ TEST_P(ParameterizedPageDiscardingHelperTest, ...@@ -301,8 +299,7 @@ TEST_P(ParameterizedPageDiscardingHelperTest,
// Pretends that the first discardable page hasn't been discarded // Pretends that the first discardable page hasn't been discarded
// successfully, the other one should be discarded in this case. // successfully, the other one should be discarded in this case.
if (GetParam() == if (GetParam() == features::DiscardStrategy::BIGGEST_RSS) {
features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS) {
::testing::InSequence in_sequence; ::testing::InSequence in_sequence;
// The first candidate is the tab with the biggest RSS. // The first candidate is the tab with the biggest RSS.
EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get())) EXPECT_CALL(*discarder(), DiscardPageNodeImpl(page_node2.get()))
...@@ -382,9 +379,8 @@ TEST_P(ParameterizedPageDiscardingHelperTest, ...@@ -382,9 +379,8 @@ TEST_P(ParameterizedPageDiscardingHelperTest,
INSTANTIATE_TEST_CASE_P( INSTANTIATE_TEST_CASE_P(
PageDiscardingHelperWithParamTest, PageDiscardingHelperWithParamTest,
ParameterizedPageDiscardingHelperTest, ParameterizedPageDiscardingHelperTest,
::testing::Values( ::testing::Values(features::DiscardStrategy::LRU,
features::UrgentDiscardingParams::DiscardStrategy::LRU, features::DiscardStrategy::BIGGEST_RSS));
features::UrgentDiscardingParams::DiscardStrategy::BIGGEST_RSS));
} // namespace policies } // namespace policies
} // namespace performance_manager } // namespace performance_manager
...@@ -99,8 +99,7 @@ constexpr base::FeatureParam<int> UrgentDiscardingParams::kDiscardStrategy; ...@@ -99,8 +99,7 @@ constexpr base::FeatureParam<int> UrgentDiscardingParams::kDiscardStrategy;
// static // static
UrgentDiscardingParams UrgentDiscardingParams::GetParams() { UrgentDiscardingParams UrgentDiscardingParams::GetParams() {
UrgentDiscardingParams params = {}; UrgentDiscardingParams params = {};
params.discard_strategy_ = params.discard_strategy_ = static_cast<DiscardStrategy>(
static_cast<UrgentDiscardingParams::DiscardStrategy>(
UrgentDiscardingParams::kDiscardStrategy.Get()); UrgentDiscardingParams::kDiscardStrategy.Get());
return params; return params;
} }
...@@ -108,10 +107,10 @@ UrgentDiscardingParams UrgentDiscardingParams::GetParams() { ...@@ -108,10 +107,10 @@ UrgentDiscardingParams UrgentDiscardingParams::GetParams() {
const base::Feature kBackgroundTabLoadingFromPerformanceManager{ const base::Feature kBackgroundTabLoadingFromPerformanceManager{
"BackgroundTabLoadingFromPerformanceManager", "BackgroundTabLoadingFromPerformanceManager",
base::FEATURE_DISABLED_BY_DEFAULT}; base::FEATURE_DISABLED_BY_DEFAULT};
#endif
const base::Feature kHighPMFMemoryPressureSignals{ const base::Feature kHighPMFDiscardPolicy{"HighPMFDiscardPolicy",
"HighPMFMemoryPressureSignals", base::FEATURE_DISABLED_BY_DEFAULT}; base::FEATURE_DISABLED_BY_DEFAULT};
#endif
} // namespace features } // namespace features
} // namespace performance_manager } // namespace performance_manager
...@@ -82,22 +82,22 @@ extern const base::Feature kPageFreezingFromPerformanceManager; ...@@ -82,22 +82,22 @@ extern const base::Feature kPageFreezingFromPerformanceManager;
// than via TabManager. // than via TabManager.
extern const base::Feature kUrgentDiscardingFromPerformanceManager; extern const base::Feature kUrgentDiscardingFromPerformanceManager;
class UrgentDiscardingParams { // The discard strategy to use.
public: // Integer values are specified to allow conversion from the integer value in
~UrgentDiscardingParams(); // the DiscardStrategy feature param.
enum class DiscardStrategy : int {
static UrgentDiscardingParams GetParams();
// The discard strategy to use.
// Integer values are specified to allow conversion from the integer value in
// the DiscardStrategy feature param.
enum class DiscardStrategy : int {
// Discards the least recently used tab among the eligible ones. This is the // Discards the least recently used tab among the eligible ones. This is the
// default strategy. // default strategy.
LRU = 0, LRU = 0,
// Discard the tab with the biggest resident set among the eligible ones. // Discard the tab with the biggest resident set among the eligible ones.
BIGGEST_RSS = 1, BIGGEST_RSS = 1,
}; };
class UrgentDiscardingParams {
public:
~UrgentDiscardingParams();
static UrgentDiscardingParams GetParams();
DiscardStrategy discard_strategy() const { return discard_strategy_; } DiscardStrategy discard_strategy() const { return discard_strategy_; }
...@@ -115,11 +115,11 @@ class UrgentDiscardingParams { ...@@ -115,11 +115,11 @@ class UrgentDiscardingParams {
// Enable background tab loading of pages (restored via session restore) // Enable background tab loading of pages (restored via session restore)
// directly from Performance Manager rather than via TabLoader. // directly from Performance Manager rather than via TabLoader.
extern const base::Feature kBackgroundTabLoadingFromPerformanceManager; extern const base::Feature kBackgroundTabLoadingFromPerformanceManager;
#endif
// Feature that controls whether or not memory pressure signals will be emitted // Feature that controls whether or not tabs should be automatically discarded
// when the total PMF is too high. // when the total PMF is too high.
extern const base::Feature kHighPMFMemoryPressureSignals; extern const base::Feature kHighPMFDiscardPolicy;
#endif
} // namespace features } // namespace features
} // namespace performance_manager } // namespace performance_manager
......
...@@ -3337,7 +3337,6 @@ test("unit_tests") { ...@@ -3337,7 +3337,6 @@ test("unit_tests") {
"../browser/performance_manager/observers/isolation_context_metrics_unittest.cc", "../browser/performance_manager/observers/isolation_context_metrics_unittest.cc",
"../browser/performance_manager/observers/metrics_collector_unittest.cc", "../browser/performance_manager/observers/metrics_collector_unittest.cc",
"../browser/performance_manager/policies/dynamic_tcmalloc_policy_chromeos_unittest.cc", "../browser/performance_manager/policies/dynamic_tcmalloc_policy_chromeos_unittest.cc",
"../browser/performance_manager/policies/high_pmf_memory_pressure_policy_unittest.cc",
"../browser/performance_manager/policies/working_set_trimmer_policy_chromeos_unittest.cc", "../browser/performance_manager/policies/working_set_trimmer_policy_chromeos_unittest.cc",
"../browser/performance_manager/policies/working_set_trimmer_policy_unittest.cc", "../browser/performance_manager/policies/working_set_trimmer_policy_unittest.cc",
"../browser/performance_manager/test_support/page_aggregator.cc", "../browser/performance_manager/test_support/page_aggregator.cc",
...@@ -4142,7 +4141,9 @@ test("unit_tests") { ...@@ -4142,7 +4141,9 @@ test("unit_tests") {
"../browser/performance_manager/persistence/site_data/unittest_utils.cc", "../browser/performance_manager/persistence/site_data/unittest_utils.cc",
"../browser/performance_manager/persistence/site_data/unittest_utils.h", "../browser/performance_manager/persistence/site_data/unittest_utils.h",
# Urgent discarding from performance_manager isn't supported on Android. # Urgent discarding from performance_manager and the High-PMF discard
# policy aren't supported on Android.
"../browser/performance_manager/policies/high_pmf_discard_policy_unittest.cc",
"../browser/performance_manager/policies/page_discarding_helper_unittest.cc", "../browser/performance_manager/policies/page_discarding_helper_unittest.cc",
"../browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc", "../browser/performance_manager/policies/urgent_page_discarding_policy_unittest.cc",
......
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