Commit 988a0b63 authored by Kuo-Hsin Yang's avatar Kuo-Hsin Yang Committed by Commit Bot

Implement GetMemoryMarginsKB

SystemMemoryPressureEvaluator::GetMarginFileParts is replaced by
GetMemoryMarginsKB, such that SystemMemoryPressureEvaluator is not
required to get the margins.

BUG=b:149833548

Change-Id: I948e576b5a36ce24590c48a36e0416cfc679979e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2418272Reviewed-by: default avatarCheng-Yu Lee <cylee@chromium.org>
Reviewed-by: default avatarBrian Geffon <bgeffon@chromium.org>
Commit-Queue: Kuo-Hsin Yang <vovoy@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814086}
parent 09aa4957
...@@ -30,17 +30,12 @@ void ChromeBrowserMainExtraPartsMemory::PostBrowserStart() { ...@@ -30,17 +30,12 @@ void ChromeBrowserMainExtraPartsMemory::PostBrowserStart() {
} }
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
if (chromeos::memory::SystemMemoryPressureEvaluator:: if (base::SysInfo::IsRunningOnChromeOS()) {
SupportsKernelNotifications()) {
cros_evaluator_ = cros_evaluator_ =
std::make_unique<chromeos::memory::SystemMemoryPressureEvaluator>( std::make_unique<chromeos::memory::SystemMemoryPressureEvaluator>(
static_cast<util::MultiSourceMemoryPressureMonitor*>( static_cast<util::MultiSourceMemoryPressureMonitor*>(
base::MemoryPressureMonitor::Get()) base::MemoryPressureMonitor::Get())
->CreateVoter()); ->CreateVoter());
} else {
LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS())
<< "No MemoryPressureMonitor created because the kernel does not "
"have support.";
} }
#endif #endif
} }
......
...@@ -216,38 +216,26 @@ class TabManagerDelegate::FocusedProcess { ...@@ -216,38 +216,26 @@ class TabManagerDelegate::FocusedProcess {
// TabManagerDelegate::MemoryStat implementation. // TabManagerDelegate::MemoryStat implementation.
// static
int TabManagerDelegate::MemoryStat::LowMemoryMarginKB() {
constexpr int kDefaultLowMemoryMarginMb = 50;
// A margin file can contain multiple values but the first one
// represents the critical memory threshold.
std::vector<int> margin_parts =
chromeos::memory::SystemMemoryPressureEvaluator::GetMarginFileParts();
if (!margin_parts.empty()) {
return margin_parts[0] * 1024;
}
return kDefaultLowMemoryMarginMb * 1024;
}
// Target memory to free is the amount which brings available // Target memory to free is the amount which brings available
// memory back to the margin. // memory back to the margin.
int TabManagerDelegate::MemoryStat::TargetMemoryToFreeKB() { int TabManagerDelegate::MemoryStat::TargetMemoryToFreeKB() {
uint64_t available_mem_mb;
if (chromeos::memory::SystemMemoryPressureEvaluator::Get()) { if (chromeos::memory::SystemMemoryPressureEvaluator::Get()) {
available_mem_mb = chromeos::memory::pressure::GetAvailableMemoryKB(); // The first output of GetMemoryMarginsKB() is the critical memory
// threshold. Low memory condition is reported if available memory is under
// the number.
return chromeos::memory::pressure::GetMemoryMarginsKB().first -
chromeos::memory::pressure::GetAvailableMemoryKB();
} else { } else {
// When TabManager::DiscardTab(LifecycleUnitDiscardReason::EXTERNAL) is // When TabManager::DiscardTab(LifecycleUnitDiscardReason::EXTERNAL) is
// called by a test or an extension, TabManagerDelegate might be used // called by an integration test, TabManagerDelegate might be used without
// without chromeos SystemMemoryPressureEvaluator, e.g. the browser test // chromeos SystemMemoryPressureEvaluator, e.g. the browser test
// DiscardTabsWithMinimizedWindow. Set available to 0 to force discarding a // DiscardTabsWithMinimizedWindow. Return 50 MB to force discarding a tab to
// tab to pass the test. // pass the test.
// TODO(vovoy): Remove this code path and modify the related browser tests.
LOG(WARNING) << "SystemMemoryPressureEvaluator is not available"; LOG(WARNING) << "SystemMemoryPressureEvaluator is not available";
available_mem_mb = 0; constexpr int kDefaultLowMemoryMarginKb = 50 * 1024;
return kDefaultLowMemoryMarginKb;
} }
return LowMemoryMarginKB() - available_mem_mb;
} }
int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB( int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB(
...@@ -577,13 +565,7 @@ void TabManagerDelegate::LowMemoryKillImpl( ...@@ -577,13 +565,7 @@ void TabManagerDelegate::LowMemoryKillImpl(
std::vector<Candidate> candidates = std::vector<Candidate> candidates =
GetSortedCandidates(GetLifecycleUnits(), arc_processes); GetSortedCandidates(GetLifecycleUnits(), arc_processes);
// TODO(semenzato): decide if TargetMemoryToFreeKB is doing real int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB();
// I/O and if it is, move to I/O thread (crbug.com/778703).
int target_memory_to_free_kb = 0;
{
base::ScopedAllowBlocking allow_blocking;
target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB();
}
MEMORY_LOG(ERROR) << "List of low memory kill candidates " MEMORY_LOG(ERROR) << "List of low memory kill candidates "
"(sorted from low priority to high priority):"; "(sorted from low priority to high priority):";
......
...@@ -281,14 +281,6 @@ class TabManagerDelegate::MemoryStat { ...@@ -281,14 +281,6 @@ class TabManagerDelegate::MemoryStat {
// Returns estimated memory to be freed if the process |handle| is killed. // Returns estimated memory to be freed if the process |handle| is killed.
virtual int EstimatedMemoryFreedKB(base::ProcessHandle handle); virtual int EstimatedMemoryFreedKB(base::ProcessHandle handle);
private:
// Returns the low memory margin system config. Low memory condition is
// reported if available memory is under the number.
static int LowMemoryMarginKB();
// Reads in an integer.
static int ReadIntFromFile(const char* file_name, int default_val);
}; };
} // namespace resource_coordinator } // namespace resource_coordinator
......
...@@ -27,6 +27,12 @@ constexpr char kRamVsSwapWeight[] = ...@@ -27,6 +27,12 @@ constexpr char kRamVsSwapWeight[] =
// The extra free to trigger kernel memory reclaim earlier. // The extra free to trigger kernel memory reclaim earlier.
constexpr char kExtraFree[] = "/proc/sys/vm/extra_free_kbytes"; constexpr char kExtraFree[] = "/proc/sys/vm/extra_free_kbytes";
// The margin mem file contains the two memory levels, the first is the
// critical level and the second is the moderate level. Note, this
// file may contain more values but only the first two are used for
// memory pressure notifications in chromeos.
constexpr char kMarginMemFile[] = "/sys/kernel/mm/chromeos-low_mem/margin";
// Values saved for user space available memory calculation. The value of // Values saved for user space available memory calculation. The value of
// |reserved_free| should not change unless min_free_kbytes or // |reserved_free| should not change unless min_free_kbytes or
// lowmem_reserve_ratio change. The value of |min_filelist| and // lowmem_reserve_ratio change. The value of |min_filelist| and
...@@ -173,9 +179,54 @@ uint64_t GetAvailableMemoryKB() { ...@@ -173,9 +179,54 @@ uint64_t GetAvailableMemoryKB() {
ram_swap_weight); ram_swap_weight);
} }
std::vector<uint64_t> GetMarginFileParts(const std::string& file) {
std::vector<uint64_t> margin_values;
std::string margin_contents;
if (base::ReadFileToStringNonBlocking(base::FilePath(file),
&margin_contents)) {
std::vector<std::string> margins =
base::SplitString(margin_contents, base::kWhitespaceASCII,
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
for (const auto& v : margins) {
uint64_t value = 0;
if (!base::StringToUint64(v, &value)) {
// If any of the values weren't parseable as an uint64_T we return
// nothing as the file format is unexpected.
LOG(ERROR) << "Unable to parse margin file contents as integer: " << v;
return std::vector<uint64_t>();
}
margin_values.push_back(value);
}
} else {
PLOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS())
<< "Unable to read margin file";
}
return margin_values;
}
namespace {
// This function would return valid margins even when there are less than 2
// margin values in the kernel margin file.
std::pair<uint64_t, uint64_t> GetMemoryMarginsKBImpl() {
const std::vector<uint64_t> margin_file_parts(
GetMarginFileParts(kMarginMemFile));
if (margin_file_parts.size() >= 2) {
return {margin_file_parts[0] * 1024, margin_file_parts[1] * 1024};
}
// Critical margin is 5.2% of total memory, moderate margin is 40% of total
// memory. See also /usr/share/cros/init/swap.sh on DUT.
base::SystemMemoryInfoKB info;
CHECK(base::GetSystemMemoryInfo(&info));
return {info.total * 13 / 250, info.total * 2 / 5};
}
} // namespace
std::pair<uint64_t, uint64_t> GetMemoryMarginsKB() { std::pair<uint64_t, uint64_t> GetMemoryMarginsKB() {
// TODO(b/149833548): Implement this function. static std::pair<uint64_t, uint64_t> result(GetMemoryMarginsKBImpl());
return {0, 0}; return result;
} }
void UpdateMemoryParameters() { void UpdateMemoryParameters() {
......
...@@ -26,6 +26,10 @@ CalculateAvailableMemoryUserSpaceKB(const base::SystemMemoryInfoKB& info, ...@@ -26,6 +26,10 @@ CalculateAvailableMemoryUserSpaceKB(const base::SystemMemoryInfoKB& info,
uint64_t min_filelist, uint64_t min_filelist,
uint64_t ram_swap_weight); uint64_t ram_swap_weight);
// Export for unittest
CHROMEOS_EXPORT std::vector<uint64_t> GetMarginFileParts(
const std::string& margin_file);
// GetAvailableMemoryKB returns the available memory in KiB. // GetAvailableMemoryKB returns the available memory in KiB.
CHROMEOS_EXPORT uint64_t GetAvailableMemoryKB(); CHROMEOS_EXPORT uint64_t GetAvailableMemoryKB();
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include "chromeos/memory/pressure/pressure.h" #include "chromeos/memory/pressure/pressure.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
TEST(MemoryPressureTest, CalculateReservedFreeKB) { TEST(MemoryPressureTest, CalculateReservedFreeKB) {
...@@ -75,3 +77,47 @@ TEST(MemoryPressureTest, CalculateAvailableMemoryUserSpaceKB) { ...@@ -75,3 +77,47 @@ TEST(MemoryPressureTest, CalculateAvailableMemoryUserSpaceKB) {
info, reserved_free, min_filelist, ram_swap_weight); info, reserved_free, min_filelist, ram_swap_weight);
ASSERT_EQ(available, uint64_t(250 * 1024)); ASSERT_EQ(available, uint64_t(250 * 1024));
} }
TEST(MemoryPressureTest, ParseMarginFileGood) {
base::ScopedTempDir tmp_dir;
ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
base::FilePath margin_file = tmp_dir.GetPath().Append("margin");
ASSERT_TRUE(base::WriteFile(margin_file, "123"));
const std::vector<uint64_t> parts1 =
chromeos::memory::pressure::GetMarginFileParts(margin_file.value());
ASSERT_EQ(1u, parts1.size());
ASSERT_EQ(123u, parts1[0]);
ASSERT_TRUE(base::WriteFile(margin_file, "123 456"));
const std::vector<uint64_t> parts2 =
chromeos::memory::pressure::GetMarginFileParts(margin_file.value());
ASSERT_EQ(2u, parts2.size());
ASSERT_EQ(123u, parts2[0]);
ASSERT_EQ(456u, parts2[1]);
}
TEST(MemoryPressureTest, ParseMarginFileBad) {
base::ScopedTempDir tmp_dir;
ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
base::FilePath margin_file = tmp_dir.GetPath().Append("margin");
// An empty margin file is bad.
ASSERT_TRUE(base::WriteFile(margin_file, ""));
ASSERT_TRUE(
chromeos::memory::pressure::GetMarginFileParts(margin_file.value())
.empty());
// The numbers will be in base10, so 4a6 would be invalid.
ASSERT_TRUE(base::WriteFile(margin_file, "123 4a6"));
ASSERT_TRUE(
chromeos::memory::pressure::GetMarginFileParts(margin_file.value())
.empty());
// The numbers must be integers.
ASSERT_TRUE(base::WriteFile(margin_file, "123.2 412.3"));
ASSERT_TRUE(
chromeos::memory::pressure::GetMarginFileParts(margin_file.value())
.empty());
}
...@@ -40,17 +40,11 @@ SystemMemoryPressureEvaluator* g_system_evaluator = nullptr; ...@@ -40,17 +40,11 @@ SystemMemoryPressureEvaluator* g_system_evaluator = nullptr;
constexpr base::TimeDelta kModerateMemoryPressureCooldownTime = constexpr base::TimeDelta kModerateMemoryPressureCooldownTime =
base::TimeDelta::FromSeconds(10); base::TimeDelta::FromSeconds(10);
// The margin mem file contains the two memory levels, the first is the
// critical level and the second is the moderate level. Note, this
// file may contain more values but only the first two are used for
// memory pressure notifications in chromeos.
constexpr char kMarginMemFile[] = "/sys/kernel/mm/chromeos-low_mem/margin";
// Converts an available memory value in MB to a memory pressure level. // Converts an available memory value in MB to a memory pressure level.
base::MemoryPressureListener::MemoryPressureLevel base::MemoryPressureListener::MemoryPressureLevel
GetMemoryPressureLevelFromAvailable(int available_mb, GetMemoryPressureLevelFromAvailable(uint64_t available_mb,
int moderate_avail_mb, uint64_t moderate_avail_mb,
int critical_avail_mb) { uint64_t critical_avail_mb) {
if (available_mb < critical_avail_mb) if (available_mb < critical_avail_mb)
return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL; return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
if (available_mb < moderate_avail_mb) if (available_mb < moderate_avail_mb)
...@@ -64,12 +58,10 @@ GetMemoryPressureLevelFromAvailable(int available_mb, ...@@ -64,12 +58,10 @@ GetMemoryPressureLevelFromAvailable(int available_mb,
SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator( SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator(
std::unique_ptr<util::MemoryPressureVoter> voter) std::unique_ptr<util::MemoryPressureVoter> voter)
: SystemMemoryPressureEvaluator( : SystemMemoryPressureEvaluator(
kMarginMemFile,
/*disable_timer_for_testing*/ false, /*disable_timer_for_testing*/ false,
std::move(voter)) {} std::move(voter)) {}
SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator( SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator(
const std::string& margin_file,
bool disable_timer_for_testing, bool disable_timer_for_testing,
std::unique_ptr<util::MemoryPressureVoter> voter) std::unique_ptr<util::MemoryPressureVoter> voter)
: util::SystemMemoryPressureEvaluator(std::move(voter)), : util::SystemMemoryPressureEvaluator(std::move(voter)),
...@@ -77,15 +69,10 @@ SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator( ...@@ -77,15 +69,10 @@ SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator(
DCHECK(g_system_evaluator == nullptr); DCHECK(g_system_evaluator == nullptr);
g_system_evaluator = this; g_system_evaluator = this;
std::vector<int> margin_parts = std::pair<uint64_t, uint64_t> margins_kb =
SystemMemoryPressureEvaluator::GetMarginFileParts(margin_file); chromeos::memory::pressure::GetMemoryMarginsKB();
critical_pressure_threshold_mb_ = margins_kb.first / 1024;
// This class SHOULD have verified kernel support by calling moderate_pressure_threshold_mb_ = margins_kb.second / 1024;
// SupportsKernelNotifications() before creating a new instance of this.
// Therefore we will check fail if we don't have multiple margin values.
CHECK_LE(2u, margin_parts.size());
critical_pressure_threshold_mb_ = margin_parts[0];
moderate_pressure_threshold_mb_ = margin_parts[1];
chromeos::memory::pressure::UpdateMemoryParameters(); chromeos::memory::pressure::UpdateMemoryParameters();
...@@ -109,63 +96,25 @@ SystemMemoryPressureEvaluator* SystemMemoryPressureEvaluator::Get() { ...@@ -109,63 +96,25 @@ SystemMemoryPressureEvaluator* SystemMemoryPressureEvaluator::Get() {
return g_system_evaluator; return g_system_evaluator;
} }
std::vector<int> SystemMemoryPressureEvaluator::GetMarginFileParts() {
static const base::NoDestructor<std::vector<int>> margin_file_parts(
GetMarginFileParts(kMarginMemFile));
return *margin_file_parts;
}
std::vector<int> SystemMemoryPressureEvaluator::GetMarginFileParts(
const std::string& file) {
std::vector<int> margin_values;
std::string margin_contents;
if (base::ReadFileToStringNonBlocking(base::FilePath(file),
&margin_contents)) {
std::vector<std::string> margins =
base::SplitString(margin_contents, base::kWhitespaceASCII,
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
for (const auto& v : margins) {
int value = -1;
if (!base::StringToInt(v, &value)) {
// If any of the values weren't parseable as an int we return
// nothing as the file format is unexpected.
LOG(ERROR) << "Unable to parse margin file contents as integer: " << v;
return std::vector<int>();
}
margin_values.push_back(value);
}
} else {
PLOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS())
<< "Unable to read margin file: " << kMarginMemFile;
}
return margin_values;
}
bool SystemMemoryPressureEvaluator::SupportsKernelNotifications() {
// Unfortunately at the moment the only way to determine if the chromeos
// kernel supports polling on the available file is to observe two values
// in the margin file, if the critical and moderate levels are specified
// there then we know the kernel must support polling on available.
return SystemMemoryPressureEvaluator::GetMarginFileParts().size() >= 2;
}
// CheckMemoryPressure will get the current memory pressure level by checking // CheckMemoryPressure will get the current memory pressure level by checking
// the available memory. // the available memory.
void SystemMemoryPressureEvaluator::CheckMemoryPressure() { void SystemMemoryPressureEvaluator::CheckMemoryPressure() {
uint64_t mem_avail_mb = uint64_t mem_avail_mb =
chromeos::memory::pressure::GetAvailableMemoryKB() / 1024; chromeos::memory::pressure::GetAvailableMemoryKB() / 1024;
CheckMemoryPressureImpl(mem_avail_mb); CheckMemoryPressureImpl(moderate_pressure_threshold_mb_,
critical_pressure_threshold_mb_, mem_avail_mb);
} }
void SystemMemoryPressureEvaluator::CheckMemoryPressureImpl( void SystemMemoryPressureEvaluator::CheckMemoryPressureImpl(
uint64_t moderate_avail_mb,
uint64_t critical_avail_mb,
uint64_t mem_avail_mb) { uint64_t mem_avail_mb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto old_vote = current_vote(); auto old_vote = current_vote();
SetCurrentVote(GetMemoryPressureLevelFromAvailable( SetCurrentVote(GetMemoryPressureLevelFromAvailable(
mem_avail_mb, moderate_pressure_threshold_mb_, mem_avail_mb, moderate_avail_mb, critical_avail_mb));
critical_pressure_threshold_mb_));
bool notify = true; bool notify = true;
if (current_vote() == if (current_vote() ==
......
...@@ -31,57 +31,30 @@ namespace memory { ...@@ -31,57 +31,30 @@ namespace memory {
class COMPONENT_EXPORT(CHROMEOS_MEMORY) SystemMemoryPressureEvaluator class COMPONENT_EXPORT(CHROMEOS_MEMORY) SystemMemoryPressureEvaluator
: public util::SystemMemoryPressureEvaluator { : public util::SystemMemoryPressureEvaluator {
public: public:
// The SystemMemoryPressureEvaluator reads the pressure levels from the
// /sys/kernel/mm/chromeos-low_mem/margin and does not need to be configured.
//
// NOTE: You should check that the kernel supports notifications by calling
// SupportsKernelNotifications() before constructing a new instance of this
// class.
explicit SystemMemoryPressureEvaluator( explicit SystemMemoryPressureEvaluator(
std::unique_ptr<util::MemoryPressureVoter> voter); std::unique_ptr<util::MemoryPressureVoter> voter);
~SystemMemoryPressureEvaluator() override; ~SystemMemoryPressureEvaluator() override;
// GetMarginFileParts returns a vector of the configured margin file values.
// The margin file contains two or more values, but we're only concerned with
// the first two. The first represents critical memory pressure, the second
// is moderate memory pressure level.
static std::vector<int> GetMarginFileParts();
// SupportsKernelNotifications will return true if the kernel supports and is
// configured for notifications on memory availability changes.
static bool SupportsKernelNotifications();
// ScheduleEarlyCheck is used by the ChromeOS tab manager delegate to force it // ScheduleEarlyCheck is used by the ChromeOS tab manager delegate to force it
// to quickly recheck pressure levels after a tab discard or some other // to quickly recheck pressure levels after a tab discard or some other
// action. // action.
void ScheduleEarlyCheck(); void ScheduleEarlyCheck();
// Returns the moderate pressure threshold as read from the margin file.
int ModeratePressureThresholdMBForTesting() const {
return moderate_pressure_threshold_mb_;
}
// Returns the critical pressure threshold as read from the margin file.
int CriticalPressureThresholdMBForTesting() const {
return critical_pressure_threshold_mb_;
}
// Returns the current system memory pressure evaluator. // Returns the current system memory pressure evaluator.
static SystemMemoryPressureEvaluator* Get(); static SystemMemoryPressureEvaluator* Get();
protected: protected:
// This constructor is only used for testing. // This constructor is only used for testing.
SystemMemoryPressureEvaluator( SystemMemoryPressureEvaluator(
const std::string& margin_file,
bool disable_timer_for_testing, bool disable_timer_for_testing,
std::unique_ptr<util::MemoryPressureVoter> voter); std::unique_ptr<util::MemoryPressureVoter> voter);
static std::vector<int> GetMarginFileParts(const std::string& margin_file);
void CheckMemoryPressure(); void CheckMemoryPressure();
// Split CheckMemoryPressure and CheckMemoryPressureImpl for testing. // Split CheckMemoryPressure and CheckMemoryPressureImpl for testing.
void CheckMemoryPressureImpl(uint64_t mem_avail_mb); void CheckMemoryPressureImpl(uint64_t moderate_avail_mb,
uint64_t critical_avail_mb,
uint64_t mem_avail_mb);
private: private:
void CheckMemoryPressureAndRecordStatistics(); void CheckMemoryPressureAndRecordStatistics();
......
...@@ -40,19 +40,16 @@ void OnMemoryPressure( ...@@ -40,19 +40,16 @@ void OnMemoryPressure(
class TestSystemMemoryPressureEvaluator : public SystemMemoryPressureEvaluator { class TestSystemMemoryPressureEvaluator : public SystemMemoryPressureEvaluator {
public: public:
TestSystemMemoryPressureEvaluator( TestSystemMemoryPressureEvaluator(
const std::string& mock_margin_file,
bool disable_timer_for_testing, bool disable_timer_for_testing,
std::unique_ptr<util::MemoryPressureVoter> voter) std::unique_ptr<util::MemoryPressureVoter> voter)
: SystemMemoryPressureEvaluator(mock_margin_file, : SystemMemoryPressureEvaluator(disable_timer_for_testing,
disable_timer_for_testing,
std::move(voter)) {} std::move(voter)) {}
static std::vector<int> GetMarginFileParts(const std::string& file) { void CheckMemoryPressureImpl(uint64_t moderate_avail_mb,
return SystemMemoryPressureEvaluator::GetMarginFileParts(file); uint64_t critical_avail_mb,
} uint64_t mem_avail_mb) {
SystemMemoryPressureEvaluator::CheckMemoryPressureImpl(
void CheckMemoryPressureImpl(uint64_t mem_avail_mb) { moderate_avail_mb, critical_avail_mb, mem_avail_mb);
SystemMemoryPressureEvaluator::CheckMemoryPressureImpl(mem_avail_mb);
} }
~TestSystemMemoryPressureEvaluator() override = default; ~TestSystemMemoryPressureEvaluator() override = default;
...@@ -61,62 +58,9 @@ class TestSystemMemoryPressureEvaluator : public SystemMemoryPressureEvaluator { ...@@ -61,62 +58,9 @@ class TestSystemMemoryPressureEvaluator : public SystemMemoryPressureEvaluator {
DISALLOW_COPY_AND_ASSIGN(TestSystemMemoryPressureEvaluator); DISALLOW_COPY_AND_ASSIGN(TestSystemMemoryPressureEvaluator);
}; };
TEST(ChromeOSSystemMemoryPressureEvaluatorTest, ParseMarginFileGood) {
base::ScopedTempDir tmp_dir;
ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
base::FilePath margin_file = tmp_dir.GetPath().Append("margin");
ASSERT_TRUE(base::WriteFile(margin_file, "123"));
const std::vector<int> parts1 =
TestSystemMemoryPressureEvaluator::GetMarginFileParts(
margin_file.value());
ASSERT_EQ(1u, parts1.size());
ASSERT_EQ(123, parts1[0]);
ASSERT_TRUE(base::WriteFile(margin_file, "123 456"));
const std::vector<int> parts2 =
TestSystemMemoryPressureEvaluator::GetMarginFileParts(
margin_file.value());
ASSERT_EQ(2u, parts2.size());
ASSERT_EQ(123, parts2[0]);
ASSERT_EQ(456, parts2[1]);
}
TEST(ChromeOSSystemMemoryPressureEvaluatorTest, ParseMarginFileBad) {
base::ScopedTempDir tmp_dir;
ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
base::FilePath margin_file = tmp_dir.GetPath().Append("margin");
// An empty margin file is bad.
ASSERT_TRUE(base::WriteFile(margin_file, ""));
ASSERT_TRUE(
TestSystemMemoryPressureEvaluator::GetMarginFileParts(margin_file.value())
.empty());
// The numbers will be in base10, so 4a6 would be invalid.
ASSERT_TRUE(base::WriteFile(margin_file, "123 4a6"));
ASSERT_TRUE(
TestSystemMemoryPressureEvaluator::GetMarginFileParts(margin_file.value())
.empty());
// The numbers must be integers.
ASSERT_TRUE(base::WriteFile(margin_file, "123.2 412.3"));
ASSERT_TRUE(
TestSystemMemoryPressureEvaluator::GetMarginFileParts(margin_file.value())
.empty());
}
TEST(ChromeOSSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) { TEST(ChromeOSSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) {
// Create a temporary directory for our margin and available files. uint64_t moderate_avail_mb = 1000;
base::ScopedTempDir tmp_dir; uint64_t critical_avail_mb = 500;
ASSERT_TRUE(tmp_dir.CreateUniqueTempDir());
base::FilePath margin_file = tmp_dir.GetPath().Append("margin");
// Set the margin values to 500 (critical) and 1000 (moderate).
const std::string kMarginContents = "500 1000";
ASSERT_TRUE(base::WriteFile(margin_file, kMarginContents));
base::test::TaskEnvironment task_environment( base::test::TaskEnvironment task_environment(
base::test::TaskEnvironment::MainThreadType::UI); base::test::TaskEnvironment::MainThreadType::UI);
...@@ -134,44 +78,39 @@ TEST(ChromeOSSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) { ...@@ -134,44 +78,39 @@ TEST(ChromeOSSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) {
monitor.ResetSystemEvaluatorForTesting(); monitor.ResetSystemEvaluatorForTesting();
auto evaluator = std::make_unique<TestSystemMemoryPressureEvaluator>( auto evaluator = std::make_unique<TestSystemMemoryPressureEvaluator>(
margin_file.value(), /*disable_timer_for_testing=*/true, /*disable_timer_for_testing=*/true, monitor.CreateVoter());
monitor.CreateVoter());
// Validate that our margin levels are as expected after being parsed from our
// synthetic margin file.
ASSERT_EQ(500, evaluator->CriticalPressureThresholdMBForTesting());
ASSERT_EQ(1000, evaluator->ModeratePressureThresholdMBForTesting());
// At this point we have no memory pressure. // At this point we have no memory pressure.
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
evaluator->current_vote()); evaluator->current_vote());
// Moderate Pressure. // Moderate Pressure.
evaluator->CheckMemoryPressureImpl(900); evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 900);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
evaluator->current_vote()); evaluator->current_vote());
// Critical Pressure. // Critical Pressure.
evaluator->CheckMemoryPressureImpl(450); evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 450);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL, ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
evaluator->current_vote()); evaluator->current_vote());
// Moderate Pressure. // Moderate Pressure.
evaluator->CheckMemoryPressureImpl(550); evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 550);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
evaluator->current_vote()); evaluator->current_vote());
// No pressure, note: this will not cause any event. // No pressure, note: this will not cause any event.
evaluator->CheckMemoryPressureImpl(1150); evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb,
1150);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE, ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
evaluator->current_vote()); evaluator->current_vote());
// Back into moderate. // Back into moderate.
evaluator->CheckMemoryPressureImpl(950); evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 950);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
evaluator->current_vote()); evaluator->current_vote());
......
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