123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- // 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 "components/memory_pressure/memory_pressure_voter.h"
- #include <numeric>
- #include "base/memory/raw_ptr.h"
- #include "base/trace_event/base_tracing.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- namespace memory_pressure {
- class MemoryPressureVoterImpl : public MemoryPressureVoter {
- public:
- explicit MemoryPressureVoterImpl(MemoryPressureVoteAggregator* aggregator)
- : aggregator_(aggregator) {}
- ~MemoryPressureVoterImpl() override {
- // Remove this voter's vote.
- if (vote_)
- aggregator_->OnVote(vote_, absl::nullopt);
- }
- MemoryPressureVoterImpl(MemoryPressureVoterImpl&&) = delete;
- MemoryPressureVoterImpl& operator=(MemoryPressureVoterImpl&&) = delete;
- void SetVote(base::MemoryPressureListener::MemoryPressureLevel level,
- bool notify_listeners) override {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- auto old_vote = vote_;
- vote_ = level;
- aggregator_->OnVote(old_vote, vote_);
- if (notify_listeners)
- aggregator_->NotifyListeners();
- }
- private:
- // This is the aggregator to which this voter's votes will be cast.
- const raw_ptr<MemoryPressureVoteAggregator> aggregator_;
- // optional<> is used here as the vote will be null until the voter's
- // first vote calculation.
- absl::optional<base::MemoryPressureListener::MemoryPressureLevel> vote_;
- SEQUENCE_CHECKER(sequence_checker_);
- };
- MemoryPressureVoteAggregator::MemoryPressureVoteAggregator(Delegate* delegate)
- : delegate_(delegate) {}
- MemoryPressureVoteAggregator::~MemoryPressureVoteAggregator() {
- DCHECK_EQ(std::accumulate(votes_.begin(), votes_.end(), 0), 0);
- }
- std::unique_ptr<MemoryPressureVoter>
- MemoryPressureVoteAggregator::CreateVoter() {
- return std::make_unique<MemoryPressureVoterImpl>(this);
- }
- void MemoryPressureVoteAggregator::OnVoteForTesting(
- absl::optional<MemoryPressureLevel> old_vote,
- absl::optional<MemoryPressureLevel> new_vote) {
- OnVote(old_vote, new_vote);
- }
- void MemoryPressureVoteAggregator::NotifyListenersForTesting() {
- NotifyListeners();
- }
- base::MemoryPressureListener::MemoryPressureLevel
- MemoryPressureVoteAggregator::EvaluateVotesForTesting() {
- return EvaluateVotes();
- }
- void MemoryPressureVoteAggregator::OnVote(
- absl::optional<MemoryPressureLevel> old_vote,
- absl::optional<MemoryPressureLevel> new_vote) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- DCHECK(old_vote || new_vote);
- if (old_vote) {
- DCHECK_LT(0u, votes_[old_vote.value()]);
- votes_[old_vote.value()]--;
- }
- if (new_vote)
- votes_[new_vote.value()]++;
- auto old_pressure_level = current_pressure_level_;
- // If the pressure level is not None then an asynchronous event will have been
- // started below, it needs to be ended.
- // Note that we record this event every time we receive a new vote to ensure
- // that the begin event doesn't get dropped during long pressure sessions.
- if (old_pressure_level ==
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) {
- TRACE_EVENT_NESTABLE_ASYNC_END0("base", "MemoryPressure::CriticalPressure",
- this);
- } else if (old_pressure_level ==
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE) {
- TRACE_EVENT_NESTABLE_ASYNC_END0("base", "MemoryPressure::ModeratePressure",
- this);
- }
- current_pressure_level_ = EvaluateVotes();
- // Start an asynchronous tracing event to record this pressure session.
- if (current_pressure_level_ ==
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("base",
- "MemoryPressure::CriticalPressure", this);
- } else if (current_pressure_level_ ==
- MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE) {
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("base",
- "MemoryPressure::ModeratePressure", this);
- }
- if (old_pressure_level != current_pressure_level_)
- delegate_->OnMemoryPressureLevelChanged(current_pressure_level_);
- }
- void MemoryPressureVoteAggregator::NotifyListeners() {
- delegate_->OnNotifyListenersRequested();
- }
- base::MemoryPressureListener::MemoryPressureLevel
- MemoryPressureVoteAggregator::EvaluateVotes() const {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- static_assert(
- base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL == 2,
- "Ensure that each memory pressure level is handled by this method.");
- if (votes_[2])
- return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
- if (votes_[1])
- return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE;
- return base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE;
- }
- void MemoryPressureVoteAggregator::SetVotesForTesting(size_t none_votes,
- size_t moderate_votes,
- size_t critical_votes) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- votes_[0] = none_votes;
- votes_[1] = moderate_votes;
- votes_[2] = critical_votes;
- }
- } // namespace memory_pressure
|