Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: content/browser/memory/memory_coordinator.cc

Issue 2579233002: Merge MemoryCoordinator and MemoryCoordinatorImpl into one class (Closed)
Patch Set: addressed comments Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 "content/browser/memory/memory_coordinator.h"
6
7 #include "base/memory/memory_coordinator_client_registry.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "content/public/browser/content_browser_client.h"
10 #include "content/public/browser/render_process_host.h"
11 #include "content/public/common/content_client.h"
12
13 namespace content {
14
15 // The implementation of MemoryCoordinatorHandle. See memory_coordinator.mojom
16 // for the role of this class.
17 class MemoryCoordinatorHandleImpl : public mojom::MemoryCoordinatorHandle {
18 public:
19 MemoryCoordinatorHandleImpl(mojom::MemoryCoordinatorHandleRequest request,
20 MemoryCoordinator* coordinator,
21 int render_process_id);
22 ~MemoryCoordinatorHandleImpl() override;
23
24 // mojom::MemoryCoordinatorHandle:
25 void AddChild(mojom::ChildMemoryCoordinatorPtr child) override;
26
27 mojom::ChildMemoryCoordinatorPtr& child() { return child_; }
28 mojo::Binding<mojom::MemoryCoordinatorHandle>& binding() { return binding_; }
29
30 private:
31 MemoryCoordinator* coordinator_;
32 int render_process_id_;
33 mojom::ChildMemoryCoordinatorPtr child_;
34 mojo::Binding<mojom::MemoryCoordinatorHandle> binding_;
35
36 DISALLOW_COPY_AND_ASSIGN(MemoryCoordinatorHandleImpl);
37 };
38
39 MemoryCoordinatorHandleImpl::MemoryCoordinatorHandleImpl(
40 mojom::MemoryCoordinatorHandleRequest request,
41 MemoryCoordinator* coordinator,
42 int render_process_id)
43 : coordinator_(coordinator),
44 render_process_id_(render_process_id),
45 binding_(this, std::move(request)) {
46 DCHECK(coordinator_);
47 }
48
49 MemoryCoordinatorHandleImpl::~MemoryCoordinatorHandleImpl() {}
50
51 void MemoryCoordinatorHandleImpl::AddChild(
52 mojom::ChildMemoryCoordinatorPtr child) {
53 DCHECK(!child_.is_bound());
54 child_ = std::move(child);
55 coordinator_->OnChildAdded(render_process_id_);
56 }
57
58 MemoryCoordinator::MemoryCoordinator()
59 : delegate_(GetContentClient()->browser()->GetMemoryCoordinatorDelegate()) {
60 }
61
62 MemoryCoordinator::~MemoryCoordinator() {}
63
64 void MemoryCoordinator::CreateHandle(
65 int render_process_id,
66 mojom::MemoryCoordinatorHandleRequest request) {
67 std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
68 new MemoryCoordinatorHandleImpl(std::move(request), this,
69 render_process_id));
70 handle->binding().set_connection_error_handler(
71 base::Bind(&MemoryCoordinator::OnConnectionError, base::Unretained(this),
72 render_process_id));
73 CreateChildInfoMapEntry(render_process_id, std::move(handle));
74 }
75
76 bool MemoryCoordinator::SetChildMemoryState(int render_process_id,
77 mojom::MemoryState memory_state) {
78 // Can't set an invalid memory state.
79 if (memory_state == mojom::MemoryState::UNKNOWN)
80 return false;
81
82 // Can't send a message to a child that doesn't exist.
83 auto iter = children_.find(render_process_id);
84 if (iter == children_.end())
85 return false;
86
87 // Can't send a message to a child that isn't bound.
88 if (!iter->second.handle->child().is_bound())
89 return false;
90
91 memory_state = OverrideGlobalState(memory_state, iter->second);
92
93 // A nop doesn't need to be sent, but is considered successful.
94 if (iter->second.memory_state == memory_state)
95 return true;
96
97 // Can't suspend the given renderer.
98 if (memory_state == mojom::MemoryState::SUSPENDED &&
99 !CanSuspendRenderer(render_process_id))
100 return false;
101
102 // Update the internal state and send the message.
103 iter->second.memory_state = memory_state;
104 iter->second.handle->child()->OnStateChange(memory_state);
105 return true;
106 }
107
108 mojom::MemoryState MemoryCoordinator::GetChildMemoryState(
109 int render_process_id) const {
110 auto iter = children_.find(render_process_id);
111 if (iter == children_.end())
112 return mojom::MemoryState::UNKNOWN;
113 return iter->second.memory_state;
114 }
115
116 void MemoryCoordinator::RecordMemoryPressure(
117 base::MemoryPressureMonitor::MemoryPressureLevel level) {
118 DCHECK(GetGlobalMemoryState() != base::MemoryState::UNKNOWN);
119 int state = static_cast<int>(GetGlobalMemoryState());
120 switch (level) {
121 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE:
122 UMA_HISTOGRAM_ENUMERATION(
123 "Memory.Coordinator.StateOnModerateNotificationReceived",
124 state, base::kMemoryStateMax);
125 break;
126 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL:
127 UMA_HISTOGRAM_ENUMERATION(
128 "Memory.Coordinator.StateOnCriticalNotificationReceived",
129 state, base::kMemoryStateMax);
130 break;
131 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE:
132 NOTREACHED();
133 }
134 }
135
136 base::MemoryState MemoryCoordinator::GetGlobalMemoryState() const {
137 return base::MemoryState::UNKNOWN;
138 }
139
140 base::MemoryState MemoryCoordinator::GetCurrentMemoryState() const {
141 return base::MemoryState::UNKNOWN;
142 }
143
144 void MemoryCoordinator::SetCurrentMemoryStateForTesting(
145 base::MemoryState memory_state) {
146 }
147
148 void MemoryCoordinator::AddChildForTesting(
149 int dummy_render_process_id, mojom::ChildMemoryCoordinatorPtr child) {
150 mojom::MemoryCoordinatorHandlePtr mch;
151 auto request = mojo::GetProxy(&mch);
152 std::unique_ptr<MemoryCoordinatorHandleImpl> handle(
153 new MemoryCoordinatorHandleImpl(std::move(request), this,
154 dummy_render_process_id));
155 handle->AddChild(std::move(child));
156 CreateChildInfoMapEntry(dummy_render_process_id, std::move(handle));
157 }
158
159 void MemoryCoordinator::OnConnectionError(int render_process_id) {
160 children_.erase(render_process_id);
161 }
162
163 bool MemoryCoordinator::CanSuspendRenderer(int render_process_id) {
164 // If there is no delegate (i.e. unittests), renderers are always suspendable.
165 if (!delegate_)
166 return true;
167 auto* render_process_host = RenderProcessHost::FromID(render_process_id);
168 if (!render_process_host || !render_process_host->IsProcessBackgrounded())
169 return false;
170 if (render_process_host->GetWorkerRefCount() > 0)
171 return false;
172 return delegate_->CanSuspendBackgroundedRenderer(render_process_id);
173 }
174
175 mojom::MemoryState MemoryCoordinator::OverrideGlobalState(
176 mojom::MemoryState memory_state,
177 const ChildInfo& child) {
178 // We don't suspend foreground renderers. Throttle them instead.
179 if (child.is_visible && memory_state == mojom::MemoryState::SUSPENDED)
180 return mojom::MemoryState::THROTTLED;
181 #if defined(OS_ANDROID)
182 // On Android, we throttle background renderers immediately.
183 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android
184 // and move this ifdef to the class.
185 if (!child.is_visible && memory_state == mojom::MemoryState::NORMAL)
186 return mojom::MemoryState::THROTTLED;
187 // TODO(bashi): Suspend background renderers after a certain period of time.
188 #endif // defined(OS_ANDROID)
189 return memory_state;
190 }
191
192 void MemoryCoordinator::SetDelegateForTesting(
193 std::unique_ptr<MemoryCoordinatorDelegate> delegate) {
194 CHECK(!delegate_);
195 delegate_ = std::move(delegate);
196 }
197
198 void MemoryCoordinator::CreateChildInfoMapEntry(
199 int render_process_id,
200 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) {
201 auto& child_info = children_[render_process_id];
202 // Process always start with normal memory state.
203 // We'll set renderer's memory state to the current global state when the
204 // corresponding renderer process is ready to communicate. Renderer processes
205 // call AddChild() when they are ready.
206 child_info.memory_state = mojom::MemoryState::NORMAL;
207 child_info.is_visible = true;
208 child_info.handle = std::move(handle);
209 }
210
211 MemoryCoordinator::ChildInfo::ChildInfo() {}
212
213 MemoryCoordinator::ChildInfo::ChildInfo(const ChildInfo& rhs) {
214 // This is a nop, but exists for compatibility with STL containers.
215 }
216
217 MemoryCoordinator::ChildInfo::~ChildInfo() {}
218
219 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/memory/memory_coordinator.h ('k') | content/browser/memory/memory_coordinator_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698