Commit 67204a8f authored by David Reveman's avatar David Reveman Committed by Chromium LUCI CQ

[fuchsia] Periodic memory pressure notifications

This makes Fuchsia behave more like Android memory pressure
signals. MODERATE and CRITICAL pressure notifications are now
sent periodically and not only when the level changes. This
is important as components expect to be able to just respond
to discrete events, which means we need periodic "refreshes"
of MODERATE and CRITICAL pressure.

Bug: 1166976
Change-Id: I829a3f3c6cd40e7753119ade19f2aac0d58a97ac
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2633682
Commit-Queue: David Reveman <reveman@chromium.org>
Reviewed-by: default avatarWez <wez@chromium.org>
Cr-Commit-Position: refs/heads/master@{#844371}
parent a74b319c
...@@ -65,10 +65,17 @@ void SystemMemoryPressureEvaluatorFuchsia::OnLevelChanged( ...@@ -65,10 +65,17 @@ void SystemMemoryPressureEvaluatorFuchsia::OnLevelChanged(
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE: case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
// By convention no notifications are sent when returning to NONE level. // By convention no notifications are sent when returning to NONE level.
SendCurrentVote(false); SendCurrentVote(false);
send_current_vote_timer_.Stop();
break; break;
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL: case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
SendCurrentVote(true); SendCurrentVote(true);
// This will reset the timer if already running.
send_current_vote_timer_.Start(
FROM_HERE, base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod,
base::BindRepeating(
&SystemMemoryPressureEvaluatorFuchsia::SendCurrentVote,
base::Unretained(this), true));
break; break;
} }
......
...@@ -9,17 +9,23 @@ ...@@ -9,17 +9,23 @@
#include <lib/fidl/cpp/binding.h> #include <lib/fidl/cpp/binding.h>
#include "base/sequence_checker.h" #include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "base/util/memory_pressure/system_memory_pressure_evaluator.h" #include "base/util/memory_pressure/system_memory_pressure_evaluator.h"
namespace util { namespace util {
class MemoryPressureVoter; class MemoryPressureVoter;
// Registers with the fuchsia.memorypressure.Provider to be notified of changes // Registers with the fuchsia.memorypressure.Provider to be notified of changes
// to the system memory pressure level. // to the system memory pressure level. Votes are sent immediately when
// memory pressure becomes MODERATE or CRITICAL, and periodically until
// memory pressure drops back down to NONE. No notifications are sent at NONE
// level.
class SystemMemoryPressureEvaluatorFuchsia class SystemMemoryPressureEvaluatorFuchsia
: public SystemMemoryPressureEvaluator, : public SystemMemoryPressureEvaluator,
public fuchsia::memorypressure::Watcher { public fuchsia::memorypressure::Watcher {
public: public:
using SystemMemoryPressureEvaluator::SendCurrentVote;
explicit SystemMemoryPressureEvaluatorFuchsia( explicit SystemMemoryPressureEvaluatorFuchsia(
std::unique_ptr<util::MemoryPressureVoter> voter); std::unique_ptr<util::MemoryPressureVoter> voter);
...@@ -37,6 +43,8 @@ class SystemMemoryPressureEvaluatorFuchsia ...@@ -37,6 +43,8 @@ class SystemMemoryPressureEvaluatorFuchsia
fidl::Binding<fuchsia::memorypressure::Watcher> binding_; fidl::Binding<fuchsia::memorypressure::Watcher> binding_;
base::RepeatingTimer send_current_vote_timer_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
}; };
......
...@@ -11,17 +11,35 @@ ...@@ -11,17 +11,35 @@
#include "base/fuchsia/test_component_context_for_process.h" #include "base/fuchsia/test_component_context_for_process.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace util { namespace util {
namespace { namespace {
class MockMemoryPressureVoter : public MemoryPressureVoter { class MockMemoryPressureVoter : public MemoryPressureVoter {
public: public:
MOCK_METHOD2(SetVote, MOCK_METHOD2(SetVote,
void(base::MemoryPressureListener::MemoryPressureLevel, bool)); void(base::MemoryPressureListener::MemoryPressureLevel, bool));
}; };
class TestSystemMemoryPressureEvaluator
: public SystemMemoryPressureEvaluatorFuchsia {
public:
TestSystemMemoryPressureEvaluator(std::unique_ptr<MemoryPressureVoter> voter)
: SystemMemoryPressureEvaluatorFuchsia(std::move(voter)) {}
TestSystemMemoryPressureEvaluator(const TestSystemMemoryPressureEvaluator&) =
delete;
TestSystemMemoryPressureEvaluator& operator=(
const TestSystemMemoryPressureEvaluator&) = delete;
MOCK_METHOD1(OnMemoryPressure,
void(base::MemoryPressureListener::MemoryPressureLevel level));
};
} // namespace } // namespace
class SystemMemoryPressureEvaluatorFuchsiaTest class SystemMemoryPressureEvaluatorFuchsiaTest
...@@ -29,7 +47,8 @@ class SystemMemoryPressureEvaluatorFuchsiaTest ...@@ -29,7 +47,8 @@ class SystemMemoryPressureEvaluatorFuchsiaTest
public fuchsia::memorypressure::testing::Provider_TestBase { public fuchsia::memorypressure::testing::Provider_TestBase {
public: public:
SystemMemoryPressureEvaluatorFuchsiaTest() SystemMemoryPressureEvaluatorFuchsiaTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {} : task_environment_(base::test::TaskEnvironment::MainThreadType::IO,
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SendPressureLevel(fuchsia::memorypressure::Level level) { void SendPressureLevel(fuchsia::memorypressure::Level level) {
base::RunLoop wait_loop; base::RunLoop wait_loop;
...@@ -53,7 +72,7 @@ class SystemMemoryPressureEvaluatorFuchsiaTest ...@@ -53,7 +72,7 @@ class SystemMemoryPressureEvaluatorFuchsiaTest
ADD_FAILURE() << "Unexpected call to method: " << name; ADD_FAILURE() << "Unexpected call to method: " << name;
} }
const base::test::SingleThreadTaskEnvironment task_environment_; base::test::SingleThreadTaskEnvironment task_environment_;
base::TestComponentContextForProcess test_context_; base::TestComponentContextForProcess test_context_;
...@@ -65,7 +84,7 @@ using SystemMemoryPressureEvaluatorFuchsiaDeathTest = ...@@ -65,7 +84,7 @@ using SystemMemoryPressureEvaluatorFuchsiaDeathTest =
TEST_F(SystemMemoryPressureEvaluatorFuchsiaDeathTest, ProviderUnavailable) { TEST_F(SystemMemoryPressureEvaluatorFuchsiaDeathTest, ProviderUnavailable) {
auto voter = std::make_unique<MockMemoryPressureVoter>(); auto voter = std::make_unique<MockMemoryPressureVoter>();
SystemMemoryPressureEvaluatorFuchsia evaluator(std::move(voter)); TestSystemMemoryPressureEvaluator evaluator(std::move(voter));
// Spin the loop to allow the evaluator to notice that the Provider is not // Spin the loop to allow the evaluator to notice that the Provider is not
// available and verify that this causes a fatal failure. // available and verify that this causes a fatal failure.
...@@ -94,7 +113,7 @@ TEST_F(SystemMemoryPressureEvaluatorFuchsiaTest, Basic) { ...@@ -94,7 +113,7 @@ TEST_F(SystemMemoryPressureEvaluatorFuchsiaTest, Basic) {
SetVote(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE, SetVote(base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
true)); true));
SystemMemoryPressureEvaluatorFuchsia evaluator(std::move(voter)); TestSystemMemoryPressureEvaluator evaluator(std::move(voter));
// Spin the loop to ensure that RegisterWatcher() is processed. // Spin the loop to ensure that RegisterWatcher() is processed.
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
...@@ -113,4 +132,69 @@ TEST_F(SystemMemoryPressureEvaluatorFuchsiaTest, Basic) { ...@@ -113,4 +132,69 @@ TEST_F(SystemMemoryPressureEvaluatorFuchsiaTest, Basic) {
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE); base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
} }
TEST_F(SystemMemoryPressureEvaluatorFuchsiaTest, Periodic) {
base::fuchsia::ScopedServiceBinding<::fuchsia::memorypressure::Provider>
publish_provider(test_context_.additional_services(), this);
MultiSourceMemoryPressureMonitor monitor;
monitor.ResetSystemEvaluatorForTesting();
testing::StrictMock<TestSystemMemoryPressureEvaluator> evaluator(
monitor.CreateVoter());
// Spin the loop to ensure that RegisterWatcher() is processed.
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(have_watcher());
base::MemoryPressureListener listener(
FROM_HERE,
base::BindRepeating(&TestSystemMemoryPressureEvaluator::OnMemoryPressure,
base::Unretained(&evaluator)));
EXPECT_CALL(
evaluator,
OnMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE));
SendPressureLevel(fuchsia::memorypressure::Level::WARNING);
EXPECT_EQ(evaluator.current_vote(),
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
testing::Mock::VerifyAndClearExpectations(&evaluator);
// Verify that MODERATE pressure level is reported periodically.
EXPECT_CALL(
evaluator,
OnMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE));
task_environment_.FastForwardBy(
base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod);
testing::Mock::VerifyAndClearExpectations(&evaluator);
EXPECT_CALL(
evaluator,
OnMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL));
SendPressureLevel(fuchsia::memorypressure::Level::CRITICAL);
EXPECT_EQ(evaluator.current_vote(),
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
testing::Mock::VerifyAndClearExpectations(&evaluator);
// Verify that CRITICAL pressure level is reported periodically.
EXPECT_CALL(
evaluator,
OnMemoryPressure(
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL));
task_environment_.FastForwardBy(
base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod);
testing::Mock::VerifyAndClearExpectations(&evaluator);
SendPressureLevel(fuchsia::memorypressure::Level::NORMAL);
EXPECT_EQ(evaluator.current_vote(),
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE);
// Verify that NONE pressure level is not reported periodically.
task_environment_.FastForwardBy(
base::MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod);
testing::Mock::VerifyAndClearExpectations(&evaluator);
}
} // namespace util } // namespace util
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