[go: nahoru, domu]

blob: 32cbc1e432e36d64c549627b86c7d799794f953d [file] [log] [blame]
Ryan Powell30287d42019-08-15 15:48:321// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/util/memory_pressure/multi_source_memory_pressure_monitor.h"
6
7#include "base/bind.h"
Hans Wennborgc3cffa62020-04-27 10:09:128#include "base/check_op.h"
Sebastien Marchand6c5354e2020-02-07 19:38:259#include "base/metrics/histogram_functions.h"
Ryan Powell30287d42019-08-15 15:48:3210#include "base/metrics/histogram_macros.h"
Sebastien Marchand6c5354e2020-02-07 19:38:2511#include "base/time/time.h"
Eric Secklerf6c544f2020-06-02 10:49:2112#include "base/trace_event/base_tracing.h"
ssid8734ea72021-03-17 18:43:5813#include "base/tracing_buildflags.h"
Ryan Powella68d66fc2019-08-19 21:32:3914#include "base/util/memory_pressure/system_memory_pressure_evaluator.h"
Ryan Powell30287d42019-08-15 15:48:3215
ssid8734ea72021-03-17 18:43:5816#if BUILDFLAG(ENABLE_BASE_TRACING)
17#include "base/trace_event/memory_pressure_level_proto.h" // no-presubmit-check
18#endif
19
Ryan Powell30287d42019-08-15 15:48:3220namespace util {
21
22MultiSourceMemoryPressureMonitor::MultiSourceMemoryPressureMonitor()
23 : current_pressure_level_(
24 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE),
25 dispatch_callback_(base::BindRepeating(
26 &base::MemoryPressureListener::NotifyMemoryPressure)),
27 aggregator_(this) {
Ryan Powell30287d42019-08-15 15:48:3228}
29
Jenny Wong6592dd42019-09-26 17:25:0730MultiSourceMemoryPressureMonitor::~MultiSourceMemoryPressureMonitor() {
31 // Destroy system evaluator early while the remaining members of this class
32 // still exist. MultiSourceMemoryPressureMonitor implements
33 // MemoryPressureVoteAggregator::Delegate, and
34 // delegate_->OnMemoryPressureLevelChanged() gets indirectly called during
35 // ~SystemMemoryPressureEvaluator().
36 system_evaluator_.reset();
37}
Ryan Powell30287d42019-08-15 15:48:3238
Sebastien Marchandc9d4cd12019-10-03 22:48:0139void MultiSourceMemoryPressureMonitor::Start() {
40 system_evaluator_ =
41 SystemMemoryPressureEvaluator::CreateDefaultSystemEvaluator(this);
42 StartMetricsTimer();
43}
44
Ryan Powell30287d42019-08-15 15:48:3245void MultiSourceMemoryPressureMonitor::StartMetricsTimer() {
46 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Ryan Powellbdc27592019-09-04 22:59:3947 // Unretained is safe here since this task is running on a timer owned by this
48 // object.
Ryan Powell30287d42019-08-15 15:48:3249 metric_timer_.Start(
50 FROM_HERE, MemoryPressureMonitor::kUMAMemoryPressureLevelPeriod,
Ryan Powellbdc27592019-09-04 22:59:3951 BindRepeating(
52 &MultiSourceMemoryPressureMonitor::RecordCurrentPressureLevel,
53 base::Unretained(this)));
Ryan Powell30287d42019-08-15 15:48:3254}
55
56void MultiSourceMemoryPressureMonitor::StopMetricsTimer() {
57 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
58 metric_timer_.Stop();
59}
60
Ryan Powellbdc27592019-09-04 22:59:3961void MultiSourceMemoryPressureMonitor::RecordCurrentPressureLevel() {
62 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
63 RecordMemoryPressure(GetCurrentPressureLevel(), /* ticks = */ 1);
64}
65
Ryan Powell30287d42019-08-15 15:48:3266base::MemoryPressureListener::MemoryPressureLevel
67MultiSourceMemoryPressureMonitor::GetCurrentPressureLevel() const {
68 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
69 return current_pressure_level_;
70}
71
72std::unique_ptr<MemoryPressureVoter>
73MultiSourceMemoryPressureMonitor::CreateVoter() {
74 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Wez861e2922020-03-01 21:14:0075 return aggregator_.CreateVoter();
Ryan Powell30287d42019-08-15 15:48:3276}
77
78void MultiSourceMemoryPressureMonitor::SetDispatchCallback(
79 const DispatchCallback& callback) {
80 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
81 dispatch_callback_ = callback;
82}
83
84void MultiSourceMemoryPressureMonitor::OnMemoryPressureLevelChanged(
85 base::MemoryPressureListener::MemoryPressureLevel level) {
86 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
Sebastien Marchand6c5354e2020-02-07 19:38:2587 DCHECK_NE(current_pressure_level_, level);
88
ssidfff7ab42021-03-04 20:03:1189 TRACE_EVENT_INSTANT(
Sebastien Marchand9df1f3d2020-03-23 18:54:3190 "base", "MultiSourceMemoryPressureMonitor::OnMemoryPressureLevelChanged",
ssidfff7ab42021-03-04 20:03:1191 [&](perfetto::EventContext ctx) {
92 auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
93 auto* data = event->set_chrome_memory_pressure_notification();
ssid8734ea72021-03-17 18:43:5894 data->set_level(
95 base::trace_event::MemoryPressureLevelToTraceEnum(level));
ssidfff7ab42021-03-04 20:03:1196 });
Sebastien Marchand9df1f3d2020-03-23 18:54:3197
Sebastien Marchand6c5354e2020-02-07 19:38:2598 // Records the duration of the latest pressure session, there are 4
99 // transitions of interest:
100 // - Moderate -> None
101 // - Moderate -> Critical
102 // - Critical -> Moderate
103 // - Critical -> None
104
105 base::TimeTicks now = base::TimeTicks::Now();
106
107 if (current_pressure_level_ !=
108 MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE) {
109 DCHECK(!last_pressure_change_timestamp_.is_null());
110 std::string histogram_name = "Memory.PressureWindowDuration.";
111 switch (current_pressure_level_) {
112 // From:
113 case MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE: {
114 // To:
115 if (level == MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE) {
116 histogram_name += "ModerateToNone";
117 } else { // MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL
118 histogram_name += "ModerateToCritical";
119 }
120 break;
121 }
122 // From:
123 case MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL: {
124 // To:
125 if (level == MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE) {
126 histogram_name += "CriticalToNone";
127 } else { // MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE
128 histogram_name += "CriticalToModerate";
129 }
130 break;
131 }
132 case MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_NONE:
133 default:
134 break;
135 }
136
137 base::UmaHistogramCustomTimes(
138 histogram_name, now - last_pressure_change_timestamp_,
139 base::TimeDelta::FromSeconds(1), base::TimeDelta::FromMinutes(10), 50);
140 }
141
142 last_pressure_change_timestamp_ = now;
143
Ryan Powell30287d42019-08-15 15:48:32144 current_pressure_level_ = level;
145}
146
147void MultiSourceMemoryPressureMonitor::OnNotifyListenersRequested() {
148 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
149 dispatch_callback_.Run(current_pressure_level_);
150}
151
Ryan Powella68d66fc2019-08-19 21:32:39152void MultiSourceMemoryPressureMonitor::ResetSystemEvaluatorForTesting() {
153 system_evaluator_.reset();
154}
155
Ryan Powell00e61aea2019-09-04 18:33:44156void MultiSourceMemoryPressureMonitor::SetSystemEvaluator(
157 std::unique_ptr<SystemMemoryPressureEvaluator> evaluator) {
158 DCHECK(!system_evaluator_);
159 system_evaluator_ = std::move(evaluator);
160}
161
Ryan Powell30287d42019-08-15 15:48:32162} // namespace util