Commit 93a5b659 authored by Brian Geffon's avatar Brian Geffon Committed by Commit Bot

CrOS: userspace swap: introduce the userspace swap policy.

This CL introduces the userspace swap policy as described in
go/userspace-swap. The policy is only concerned with the "when"
of userspace swap and not the actual userspace swap implementation
itself. The swapping part will be handled in a later CL which will
contain the "mechanism" part of userspace swapping.

This CL uses information about renderers to determine if they are
eligible to be swapped and if so it will trigger the userspace
swap process to the mechanism.

BUG=chromium:1067833

Change-Id: I9a1f635c96401701f4c1cad44ba403582f2af828
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2295926
Commit-Queue: Brian Geffon <bgeffon@chromium.org>
Reviewed-by: default avatarChris Hamilton <chrisha@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarMatthew Denton <mpdenton@chromium.org>
Cr-Commit-Position: refs/heads/master@{#791615}
parent 1549acb5
...@@ -3916,6 +3916,8 @@ static_library("browser") { ...@@ -3916,6 +3916,8 @@ static_library("browser") {
"notifications/web_page_notifier_controller.h", "notifications/web_page_notifier_controller.h",
"performance_manager/mechanisms/working_set_trimmer_chromeos.cc", "performance_manager/mechanisms/working_set_trimmer_chromeos.cc",
"performance_manager/mechanisms/working_set_trimmer_chromeos.h", "performance_manager/mechanisms/working_set_trimmer_chromeos.h",
"performance_manager/policies/userspace_swap_policy_chromeos.cc",
"performance_manager/policies/userspace_swap_policy_chromeos.h",
"performance_manager/policies/working_set_trimmer_policy_chromeos.cc", "performance_manager/policies/working_set_trimmer_policy_chromeos.cc",
"performance_manager/policies/working_set_trimmer_policy_chromeos.h", "performance_manager/policies/working_set_trimmer_policy_chromeos.h",
"platform_util_chromeos.cc", "platform_util_chromeos.cc",
......
...@@ -35,10 +35,13 @@ ...@@ -35,10 +35,13 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "base/allocator/buildflags.h" #include "base/allocator/buildflags.h"
#include "chrome/browser/performance_manager/policies/userspace_swap_policy_chromeos.h"
#if BUILDFLAG(USE_TCMALLOC) #if BUILDFLAG(USE_TCMALLOC)
#include "chrome/browser/performance_manager/policies/dynamic_tcmalloc_policy_chromeos.h" #include "chrome/browser/performance_manager/policies/dynamic_tcmalloc_policy_chromeos.h"
#include "chrome/common/performance_manager/mojom/tcmalloc.mojom.h" #include "chrome/common/performance_manager/mojom/tcmalloc.mojom.h"
#endif // BUILDFLAG(USE_TCMALLOC) #endif // BUILDFLAG(USE_TCMALLOC)
#endif // defined(OS_CHROMEOS) #endif // defined(OS_CHROMEOS)
#if !defined(OS_ANDROID) #if !defined(OS_ANDROID)
...@@ -91,6 +94,12 @@ void ChromeBrowserMainExtraPartsPerformanceManager::CreatePoliciesAndDecorators( ...@@ -91,6 +94,12 @@ void ChromeBrowserMainExtraPartsPerformanceManager::CreatePoliciesAndDecorators(
} }
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
if (performance_manager::policies::UserspaceSwapPolicy::
UserspaceSwapSupportedAndEnabled()) {
graph->PassToGraph(
std::make_unique<performance_manager::policies::UserspaceSwapPolicy>());
}
#if BUILDFLAG(USE_TCMALLOC) #if BUILDFLAG(USE_TCMALLOC)
if (base::FeatureList::IsEnabled( if (base::FeatureList::IsEnabled(
performance_manager::features::kDynamicTcmallocTuning)) { performance_manager::features::kDynamicTcmallocTuning)) {
......
// 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_POLICIES_USERSPACE_SWAP_POLICY_CHROMEOS_H_
#define CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_USERSPACE_SWAP_POLICY_CHROMEOS_H_
#include "base/macros.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/resource_coordinator/lifecycle_unit_observer.h"
#include "components/performance_manager/public/graph/graph.h"
#include "components/performance_manager/public/graph/process_node.h"
namespace chromeos {
namespace memory {
namespace userspace_swap {
struct UserspaceSwapConfig;
} // namespace userspace_swap
} // namespace memory
} // namespace chromeos
namespace performance_manager {
namespace policies {
// UserspaceSwapPolicy is a policy which will trigger a renderer to swap itself
// via userspace.
class UserspaceSwapPolicy : public GraphOwned,
public ProcessNode::ObserverDefaultImpl {
public:
UserspaceSwapPolicy();
~UserspaceSwapPolicy() override;
// GraphOwned implementation:
void OnPassedToGraph(Graph* graph) override;
void OnTakenFromGraph(Graph* graph) override;
// ProcessNodeObserver implementation:
void OnAllFramesInProcessFrozen(const ProcessNode* process_node) override;
void OnProcessNodeAdded(const ProcessNode* process_node) override;
void OnProcessLifetimeChange(const ProcessNode* process_node) override;
// MemoryPressureListener impl:
void OnMemoryPressure(
base::MemoryPressureListener::MemoryPressureLevel level);
// Returns true if running on a platform that supports the kernel features
// necessary for userspace swapping, most important would be userfaultfd(2).
static bool UserspaceSwapSupportedAndEnabled();
protected:
explicit UserspaceSwapPolicy(
const chromeos::memory::userspace_swap::UserspaceSwapConfig& config);
// The following methods are virtual for testing.
virtual void SwapNodesOnGraph();
virtual bool InitializeProcessNode(const ProcessNode* process_node);
virtual uint64_t GetTotalSwapFileUsageBytes();
virtual uint64_t GetSwapDeviceFreeSpaceBytes();
virtual void SwapProcessNode(const ProcessNode* process_node);
virtual uint64_t GetProcessNodeSwapFileUsageBytes(
const ProcessNode* process_node);
virtual uint64_t GetProcessNodeReclaimedBytes(
const ProcessNode* process_node);
virtual bool IsPageNodeVisible(const PageNode* page_node);
virtual bool IsPageNodeAudible(const PageNode* page_node);
virtual bool IsPageNodeLoading(const PageNode* page_node);
virtual base::TimeDelta GetTimeSinceLastVisibilityChange(
const PageNode* page_node);
// IsEligibleToSwap will return true if the |page_node| belonging to the
// |process_node| meets the configured criteria to be swap eligible. The
// |page_node| is optional, if it's provided the visibility, audible, and
// loading states will also be used to determine eligibility. The situation
// where the |page_node| is omitted is when the process is frozen.
virtual bool IsEligibleToSwap(const ProcessNode* process_node,
const PageNode* page_node);
// Returns the time in which this process was last swapped, |process_node| is
// the node in which you want to update.
virtual base::TimeTicks GetLastSwapTime(const ProcessNode* process_node);
// We cache the config object since it cannot change, this makes the code
// easier to read and testing also becomes easier.
const chromeos::memory::userspace_swap::UserspaceSwapConfig& config_;
// Keeps track of the last time we walked the graph looking for processes to
// swap, the frequency we walk the graph is configurable.
base::TimeTicks last_graph_walk_;
// We periodically check the amount of free space on the device that backs our
// swap files to make sure we're not letting it get below the configured
// limit, we don't want to completely exhaust free space on a device.
base::TimeTicks last_device_space_check_;
uint64_t backing_store_available_bytes_ = 0;
Graph* graph_ = nullptr;
base::Optional<base::MemoryPressureListener> memory_pressure_listener_;
private:
// A helper method which sets the last trim time to the specified time.
void SetLastSwapTime(const ProcessNode* process_node, base::TimeTicks time);
void PrintAllSwapMetrics();
std::unique_ptr<base::RepeatingTimer> metrics_timer_ =
std::make_unique<base::RepeatingTimer>();
base::WeakPtrFactory<UserspaceSwapPolicy> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(UserspaceSwapPolicy);
};
} // namespace policies
} // namespace performance_manager
#endif // CHROME_BROWSER_PERFORMANCE_MANAGER_POLICIES_USERSPACE_SWAP_POLICY_CHROMEOS_H_
...@@ -3340,6 +3340,7 @@ test("unit_tests") { ...@@ -3340,6 +3340,7 @@ 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/userspace_swap_policy_chromeos_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",
...@@ -3704,6 +3705,7 @@ test("unit_tests") { ...@@ -3704,6 +3705,7 @@ test("unit_tests") {
} }
if (is_chromeos) { if (is_chromeos) {
sources += [ sources += [
"../../chromeos/memory/userspace_swap/userspace_swap.cc",
"../browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc", "../browser/device_identity/chromeos/device_oauth2_token_store_chromeos_unittest.cc",
"../browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc", "../browser/ui/webui/certificate_provisioning_ui_handler_unittest.cc",
"../browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils_unittest.cc", "../browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils_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