| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chromeos/ash/components/memory/swap_configuration.h" |
| |
| #include "base/component_export.h" |
| #include "base/feature_list.h" |
| #include "base/functional/bind.h" |
| #include "base/metrics/field_trial_params.h" |
| #include "base/system/sys_info.h" |
| #include "chromeos/ash/components/dbus/resourced/resourced_client.h" |
| |
| namespace ash { |
| |
| // There are going to be 2 separate experiments for memory pressure signal, one |
| // for ARC enabled users and one for ARC disabled users. |
| BASE_FEATURE(kCrOSMemoryPressureSignalStudyNonArc, |
| "ChromeOSMemoryPressureSignalStudyNonArc", |
| base::FEATURE_ENABLED_BY_DEFAULT); |
| |
| const base::FeatureParam<int> kCrOSMemoryPressureSignalStudyNonArcModerateBps{ |
| &kCrOSMemoryPressureSignalStudyNonArc, "moderate_threshold_percentage", |
| 4000}; |
| |
| const base::FeatureParam<int> kCrOSMemoryPressureSignalStudyNonArcCriticalBps{ |
| &kCrOSMemoryPressureSignalStudyNonArc, "critical_threshold_percentage", |
| 1500}; |
| |
| const base::FeatureParam<int> |
| kCrOSMemoryPressureSignalStudyNonArcCriticalProtectedBps{ |
| &kCrOSMemoryPressureSignalStudyNonArc, |
| "critical_protected_threshold_percentage", 750}; |
| |
| BASE_FEATURE(kCrOSMemoryPressureSignalStudyArc, |
| "ChromeOSMemoryPressureSignalStudyArc", |
| base::FEATURE_ENABLED_BY_DEFAULT); |
| |
| const base::FeatureParam<int> kCrOSMemoryPressureSignalStudyArcModerateBps{ |
| &kCrOSMemoryPressureSignalStudyArc, "moderate_threshold_percentage", 4000}; |
| |
| const base::FeatureParam<int> kCrOSMemoryPressureSignalStudyArcCriticalBps{ |
| &kCrOSMemoryPressureSignalStudyArc, "critical_threshold_percentage", 800}; |
| |
| const base::FeatureParam<int> |
| kCrOSMemoryPressureSignalStudyArcCriticalProtectedBps{ |
| &kCrOSMemoryPressureSignalStudyArc, |
| "critical_protected_threshold_percentage", 800}; |
| |
| namespace { |
| |
| void ConfigureResourcedPressureThreshold(bool arc_enabled) { |
| if (!ResourcedClient::Get()) { |
| return; |
| } |
| |
| bool experiment_enabled = false; |
| uint32_t moderate_bps = 0; |
| uint32_t critical_bps = 0; |
| uint32_t critical_protected_bps = 0; |
| // Limit the critical protected threshold to 600 MiB to avoid setting large |
| // critical protected threshold on large RAM device. Setting Large threshold |
| // could easily discard protected pages. |
| const int kProtectedThresholdLimitMb = 600; |
| const int kRatioToBps = 10000; |
| // limit_bps = (limit_mb / total_mb) * ratio_to_bps, rearrange the |
| // multiplication to avoid floating point arithmetic. |
| int protected_threshold_limit_bps = |
| static_cast<uint32_t>(kProtectedThresholdLimitMb * kRatioToBps / |
| base::SysInfo::AmountOfPhysicalMemory().InMiB()); |
| if (arc_enabled) { |
| experiment_enabled = |
| base::FeatureList::IsEnabled(kCrOSMemoryPressureSignalStudyArc); |
| if (experiment_enabled) { |
| moderate_bps = kCrOSMemoryPressureSignalStudyArcModerateBps.Get(); |
| critical_bps = kCrOSMemoryPressureSignalStudyArcCriticalBps.Get(); |
| critical_protected_bps = |
| std::min(protected_threshold_limit_bps, |
| kCrOSMemoryPressureSignalStudyArcCriticalProtectedBps.Get()); |
| } |
| } else { |
| experiment_enabled = |
| base::FeatureList::IsEnabled(kCrOSMemoryPressureSignalStudyNonArc); |
| if (experiment_enabled) { |
| moderate_bps = kCrOSMemoryPressureSignalStudyNonArcModerateBps.Get(); |
| critical_bps = kCrOSMemoryPressureSignalStudyNonArcCriticalBps.Get(); |
| critical_protected_bps = std::min( |
| protected_threshold_limit_bps, |
| kCrOSMemoryPressureSignalStudyNonArcCriticalProtectedBps.Get()); |
| } |
| } |
| |
| if (experiment_enabled) { |
| // We need to send a debus message to resourced with the critical threshold |
| // value (in bps). |
| 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) |
| << "%"; |
| ResourcedClient::MemoryMargins margins = { |
| .moderate_bps = moderate_bps, |
| .critical_bps = critical_bps, |
| .critical_protected_bps = critical_protected_bps}; |
| ResourcedClient::Get()->SetMemoryMargins(margins); |
| } |
| } |
| |
| } // namespace |
| |
| void ConfigureSwap(bool arc_enabled) { |
| ConfigureResourcedPressureThreshold(arc_enabled); |
| } |
| |
| } // namespace ash |