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() {
}
#if defined(OS_CHROMEOS)
if (chromeos::memory::SystemMemoryPressureEvaluator::
SupportsKernelNotifications()) {
if (base::SysInfo::IsRunningOnChromeOS()) {
cros_evaluator_ =
std::make_unique<chromeos::memory::SystemMemoryPressureEvaluator>(
static_cast<util::MultiSourceMemoryPressureMonitor*>(
base::MemoryPressureMonitor::Get())
->CreateVoter());
} else {
LOG_IF(ERROR, base::SysInfo::IsRunningOnChromeOS())
<< "No MemoryPressureMonitor created because the kernel does not "
"have support.";
}
#endif
}
......
......@@ -216,38 +216,26 @@ class TabManagerDelegate::FocusedProcess {
// 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
// memory back to the margin.
int TabManagerDelegate::MemoryStat::TargetMemoryToFreeKB() {
uint64_t available_mem_mb;
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 {
// When TabManager::DiscardTab(LifecycleUnitDiscardReason::EXTERNAL) is
// called by a test or an extension, TabManagerDelegate might be used
// without chromeos SystemMemoryPressureEvaluator, e.g. the browser test
// DiscardTabsWithMinimizedWindow. Set available to 0 to force discarding a
// tab to pass the test.
// called by an integration test, TabManagerDelegate might be used without
// chromeos SystemMemoryPressureEvaluator, e.g. the browser test
// DiscardTabsWithMinimizedWindow. Return 50 MB to force discarding a tab to
// pass the test.
// TODO(vovoy): Remove this code path and modify the related browser tests.
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(
......@@ -577,13 +565,7 @@ void TabManagerDelegate::LowMemoryKillImpl(
std::vector<Candidate> candidates =
GetSortedCandidates(GetLifecycleUnits(), arc_processes);
// TODO(semenzato): decide if TargetMemoryToFreeKB is doing real
// 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();
}
int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB();
MEMORY_LOG(ERROR) << "List of low memory kill candidates "
"(sorted from low priority to high priority):";
......
......@@ -281,14 +281,6 @@ class TabManagerDelegate::MemoryStat {
// Returns estimated memory to be freed if the process |handle| is killed.
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
......
......@@ -27,6 +27,12 @@ constexpr char kRamVsSwapWeight[] =
// The extra free to trigger kernel memory reclaim earlier.
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
// |reserved_free| should not change unless min_free_kbytes or
// lowmem_reserve_ratio change. The value of |min_filelist| and
......@@ -173,9 +179,54 @@ uint64_t GetAvailableMemoryKB() {
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() {
// TODO(b/149833548): Implement this function.
return {0, 0};
static std::pair<uint64_t, uint64_t> result(GetMemoryMarginsKBImpl());
return result;
}
void UpdateMemoryParameters() {
......
......@@ -26,6 +26,10 @@ CalculateAvailableMemoryUserSpaceKB(const base::SystemMemoryInfoKB& info,
uint64_t min_filelist,
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.
CHROMEOS_EXPORT uint64_t GetAvailableMemoryKB();
......
......@@ -4,6 +4,8 @@
#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"
TEST(MemoryPressureTest, CalculateReservedFreeKB) {
......@@ -75,3 +77,47 @@ TEST(MemoryPressureTest, CalculateAvailableMemoryUserSpaceKB) {
info, reserved_free, min_filelist, ram_swap_weight);
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;
constexpr base::TimeDelta kModerateMemoryPressureCooldownTime =
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.
base::MemoryPressureListener::MemoryPressureLevel
GetMemoryPressureLevelFromAvailable(int available_mb,
int moderate_avail_mb,
int critical_avail_mb) {
GetMemoryPressureLevelFromAvailable(uint64_t available_mb,
uint64_t moderate_avail_mb,
uint64_t critical_avail_mb) {
if (available_mb < critical_avail_mb)
return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
if (available_mb < moderate_avail_mb)
......@@ -64,12 +58,10 @@ GetMemoryPressureLevelFromAvailable(int available_mb,
SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator(
std::unique_ptr<util::MemoryPressureVoter> voter)
: SystemMemoryPressureEvaluator(
kMarginMemFile,
/*disable_timer_for_testing*/ false,
std::move(voter)) {}
SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator(
const std::string& margin_file,
bool disable_timer_for_testing,
std::unique_ptr<util::MemoryPressureVoter> voter)
: util::SystemMemoryPressureEvaluator(std::move(voter)),
......@@ -77,15 +69,10 @@ SystemMemoryPressureEvaluator::SystemMemoryPressureEvaluator(
DCHECK(g_system_evaluator == nullptr);
g_system_evaluator = this;
std::vector<int> margin_parts =
SystemMemoryPressureEvaluator::GetMarginFileParts(margin_file);
// This class SHOULD have verified kernel support by calling
// 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];
std::pair<uint64_t, uint64_t> margins_kb =
chromeos::memory::pressure::GetMemoryMarginsKB();
critical_pressure_threshold_mb_ = margins_kb.first / 1024;
moderate_pressure_threshold_mb_ = margins_kb.second / 1024;
chromeos::memory::pressure::UpdateMemoryParameters();
......@@ -109,63 +96,25 @@ SystemMemoryPressureEvaluator* SystemMemoryPressureEvaluator::Get() {
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
// the available memory.
void SystemMemoryPressureEvaluator::CheckMemoryPressure() {
uint64_t mem_avail_mb =
chromeos::memory::pressure::GetAvailableMemoryKB() / 1024;
CheckMemoryPressureImpl(mem_avail_mb);
CheckMemoryPressureImpl(moderate_pressure_threshold_mb_,
critical_pressure_threshold_mb_, mem_avail_mb);
}
void SystemMemoryPressureEvaluator::CheckMemoryPressureImpl(
uint64_t moderate_avail_mb,
uint64_t critical_avail_mb,
uint64_t mem_avail_mb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto old_vote = current_vote();
SetCurrentVote(GetMemoryPressureLevelFromAvailable(
mem_avail_mb, moderate_pressure_threshold_mb_,
critical_pressure_threshold_mb_));
mem_avail_mb, moderate_avail_mb, critical_avail_mb));
bool notify = true;
if (current_vote() ==
......
......@@ -31,57 +31,30 @@ namespace memory {
class COMPONENT_EXPORT(CHROMEOS_MEMORY) SystemMemoryPressureEvaluator
: public util::SystemMemoryPressureEvaluator {
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(
std::unique_ptr<util::MemoryPressureVoter> voter);
~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
// to quickly recheck pressure levels after a tab discard or some other
// action.
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.
static SystemMemoryPressureEvaluator* Get();
protected:
// This constructor is only used for testing.
SystemMemoryPressureEvaluator(
const std::string& margin_file,
bool disable_timer_for_testing,
std::unique_ptr<util::MemoryPressureVoter> voter);
static std::vector<int> GetMarginFileParts(const std::string& margin_file);
void CheckMemoryPressure();
// 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:
void CheckMemoryPressureAndRecordStatistics();
......
......@@ -40,19 +40,16 @@ void OnMemoryPressure(
class TestSystemMemoryPressureEvaluator : public SystemMemoryPressureEvaluator {
public:
TestSystemMemoryPressureEvaluator(
const std::string& mock_margin_file,
bool disable_timer_for_testing,
std::unique_ptr<util::MemoryPressureVoter> voter)
: SystemMemoryPressureEvaluator(mock_margin_file,
disable_timer_for_testing,
: SystemMemoryPressureEvaluator(disable_timer_for_testing,
std::move(voter)) {}
static std::vector<int> GetMarginFileParts(const std::string& file) {
return SystemMemoryPressureEvaluator::GetMarginFileParts(file);
}
void CheckMemoryPressureImpl(uint64_t mem_avail_mb) {
SystemMemoryPressureEvaluator::CheckMemoryPressureImpl(mem_avail_mb);
void CheckMemoryPressureImpl(uint64_t moderate_avail_mb,
uint64_t critical_avail_mb,
uint64_t mem_avail_mb) {
SystemMemoryPressureEvaluator::CheckMemoryPressureImpl(
moderate_avail_mb, critical_avail_mb, mem_avail_mb);
}
~TestSystemMemoryPressureEvaluator() override = default;
......@@ -61,62 +58,9 @@ class TestSystemMemoryPressureEvaluator : public SystemMemoryPressureEvaluator {
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) {
// Create a temporary directory for our margin and available files.
base::ScopedTempDir tmp_dir;
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));
uint64_t moderate_avail_mb = 1000;
uint64_t critical_avail_mb = 500;
base::test::TaskEnvironment task_environment(
base::test::TaskEnvironment::MainThreadType::UI);
......@@ -134,44 +78,39 @@ TEST(ChromeOSSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) {
monitor.ResetSystemEvaluatorForTesting();
auto evaluator = std::make_unique<TestSystemMemoryPressureEvaluator>(
margin_file.value(), /*disable_timer_for_testing=*/true,
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());
/*disable_timer_for_testing=*/true, monitor.CreateVoter());
// At this point we have no memory pressure.
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
evaluator->current_vote());
// Moderate Pressure.
evaluator->CheckMemoryPressureImpl(900);
evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 900);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
evaluator->current_vote());
// Critical Pressure.
evaluator->CheckMemoryPressureImpl(450);
evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 450);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
evaluator->current_vote());
// Moderate Pressure.
evaluator->CheckMemoryPressureImpl(550);
evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 550);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
evaluator->current_vote());
// No pressure, note: this will not cause any event.
evaluator->CheckMemoryPressureImpl(1150);
evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb,
1150);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
evaluator->current_vote());
// Back into moderate.
evaluator->CheckMemoryPressureImpl(950);
evaluator->CheckMemoryPressureImpl(moderate_avail_mb, critical_avail_mb, 950);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
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