blob: 55a40d5ba6dc13175b9d0b506c82ceb32c5f84b6 [file] [log] [blame]
// Copyright 2019 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 "chromeos/memory/swap_configuration.h"
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon/debug_daemon_client.h"
#include "chromeos/dbus/resourced/resourced_client.h"
namespace chromeos {
const base::Feature kCrOSTuneMinFilelist{"CrOSTuneMinFilelist",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::FeatureParam<int> kCrOSMinFilelistMb{&kCrOSTuneMinFilelist,
"CrOSMinFilelistMb", -1};
const base::Feature kCrOSTuneRamVsSwapWeight{"CrOSTuneRamVsSwapWeight",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::FeatureParam<int> kCrOSRamVsSwapWeight{&kCrOSTuneRamVsSwapWeight,
"CrOSRamVsSwapWeight", -1};
const base::Feature kCrOSTuneExtraFree{"CrOSTuneExtraFree",
base::FEATURE_DISABLED_BY_DEFAULT};
const base::FeatureParam<int> kCrOSExtraFreeMb{&kCrOSTuneExtraFree,
"CrOSExtraFreeMb", -1};
const base::Feature kCrOSMemoryPressureSignalStudy{
"ChromeOSMemoryPressureSignalStudy", base::FEATURE_DISABLED_BY_DEFAULT};
const base::FeatureParam<int>
kCrOSMemoryPressureSignalStudyCriticalThresholdPrecentageBps{
&kCrOSMemoryPressureSignalStudy, "critical_threshold_percentage", 520};
const base::FeatureParam<int>
kCrOSMemoryPressureSignalStudyModerateThresholdPrecentageBps{
&kCrOSMemoryPressureSignalStudy, "moderate_threshold_percentage", 4000};
namespace {
constexpr const char kMinFilelist[] = "min_filelist";
constexpr const char kRamVsSwapWeight[] = "ram_vs_swap_weight";
constexpr const char kExtraFree[] = "extra_free";
void OnSwapParameterSet(std::string parameter,
absl::optional<std::string> res) {
LOG_IF(ERROR, !res.has_value())
<< "Setting swap paramter " << parameter << " failed.";
LOG_IF(ERROR, res.has_value() && !res.value().empty())
<< "Setting swap parameter " << parameter
<< " returned error: " << res.value();
}
void ConfigureMinFilelistIfEnabled() {
if (!base::FeatureList::IsEnabled(kCrOSTuneMinFilelist)) {
return;
}
chromeos::DebugDaemonClient* debugd_client =
chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
CHECK(debugd_client);
int min_mb = kCrOSMinFilelistMb.Get();
if (min_mb < 0) {
LOG(ERROR) << "Min Filelist MB is enabled with an invalid value: "
<< min_mb;
return;
}
VLOG(1) << "Setting min filelist to " << min_mb << "MB";
debugd_client->SetSwapParameter(
kMinFilelist, min_mb, base::BindOnce(&OnSwapParameterSet, kMinFilelist));
}
void ConfigureRamVsSwapWeightIfEnabled() {
if (!base::FeatureList::IsEnabled(kCrOSTuneRamVsSwapWeight))
return;
chromeos::DebugDaemonClient* debugd_client =
chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
CHECK(debugd_client);
int swap_weight = kCrOSRamVsSwapWeight.Get();
if (swap_weight < 0) {
LOG(ERROR) << "Ram vs Swap weight must be greater than or equal to 0, "
"invalid value: "
<< swap_weight;
return;
}
VLOG(1) << "Setting ram vs swap weight to: " << swap_weight;
debugd_client->SetSwapParameter(
kRamVsSwapWeight, swap_weight,
base::BindOnce(&OnSwapParameterSet, kRamVsSwapWeight));
}
void ConfigureExtraFreeIfEnabled() {
if (!base::FeatureList::IsEnabled(kCrOSTuneExtraFree))
return;
chromeos::DebugDaemonClient* debugd_client =
chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
CHECK(debugd_client);
int extra_free = kCrOSExtraFreeMb.Get();
if (extra_free < 0) {
LOG(ERROR)
<< "Extra free must be greater than or equal to 0, invalid value: "
<< extra_free;
return;
}
VLOG(1) << "Setting extra_free mb to: " << extra_free;
debugd_client->SetSwapParameter(
kExtraFree, extra_free, base::BindOnce(&OnSwapParameterSet, kExtraFree));
}
void OnMemoryMarginsSet(bool result, uint64_t critical, uint64_t moderate) {
if (!result) {
LOG(ERROR) << "Unable to set critical memory margins via resourced";
return;
}
LOG(WARNING) << "Set memory margins via resourced to: " << critical
<< "KB and " << moderate << "KB";
}
void ConfigureResourcedPressureThreshold() {
if (!chromeos::ResourcedClient::Get()) {
return;
}
if (base::FeatureList::IsEnabled(kCrOSMemoryPressureSignalStudy)) {
// We need to send a debus message to resourced with the critical threshold
// value (in bps).
int critical_bps =
kCrOSMemoryPressureSignalStudyCriticalThresholdPrecentageBps.Get();
int moderate_bps =
kCrOSMemoryPressureSignalStudyModerateThresholdPrecentageBps.Get();
if (critical_bps < 520 || critical_bps > 2500 || moderate_bps > 7500 ||
moderate_bps < 2000 || critical_bps >= moderate_bps) {
// To avoid a potentially catastrophic misconfiguration we
// only allow critical values between 5.2% and 25%, moderate between 20%
// and 75%, and moderate must be greater than critical.
LOG(ERROR) << "Invalid values specified for memory thresholds: "
<< critical_bps << " and " << moderate_bps;
return;
}
LOG(WARNING) << "Overriding memory thresholds with values "
<< (critical_bps / 100.0) << "% and " << (moderate_bps / 100.0)
<< "%";
chromeos::ResourcedClient::Get()->SetMemoryMarginsBps(
critical_bps, moderate_bps, base::BindOnce(&OnMemoryMarginsSet));
}
}
} // namespace
void ConfigureSwap() {
ConfigureResourcedPressureThreshold();
ConfigureExtraFreeIfEnabled();
ConfigureRamVsSwapWeightIfEnabled();
ConfigureMinFilelistIfEnabled();
}
} // namespace chromeos