OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/memory/memory_coordinator_impl.h" | 5 #include "content/browser/memory/memory_coordinator_impl.h" |
6 | 6 |
7 #include "base/memory/memory_coordinator_client_registry.h" | 7 #include "base/memory/memory_coordinator_client_registry.h" |
8 #include "base/metrics/histogram_macros.h" | 8 #include "base/metrics/histogram_macros.h" |
9 #include "base/process/process_handle.h" | 9 #include "base/process/process_handle.h" |
10 #include "base/process/process_metrics.h" | 10 #include "base/process/process_metrics.h" |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
188 std::unique_ptr<MemoryCoordinatorHandleImpl> handle( | 188 std::unique_ptr<MemoryCoordinatorHandleImpl> handle( |
189 new MemoryCoordinatorHandleImpl(std::move(request), this, | 189 new MemoryCoordinatorHandleImpl(std::move(request), this, |
190 render_process_id)); | 190 render_process_id)); |
191 handle->binding().set_connection_error_handler( | 191 handle->binding().set_connection_error_handler( |
192 base::Bind(&MemoryCoordinatorImpl::OnConnectionError, | 192 base::Bind(&MemoryCoordinatorImpl::OnConnectionError, |
193 base::Unretained(this), render_process_id)); | 193 base::Unretained(this), render_process_id)); |
194 CreateChildInfoMapEntry(render_process_id, std::move(handle)); | 194 CreateChildInfoMapEntry(render_process_id, std::move(handle)); |
195 } | 195 } |
196 | 196 |
197 bool MemoryCoordinatorImpl::SetChildMemoryState(int render_process_id, | 197 bool MemoryCoordinatorImpl::SetChildMemoryState(int render_process_id, |
198 mojom::MemoryState memory_state) { | 198 MemoryState memory_state) { |
199 // Can't set an invalid memory state. | 199 // Can't set an invalid memory state. |
200 if (memory_state == mojom::MemoryState::UNKNOWN) | 200 if (memory_state == MemoryState::UNKNOWN) |
201 return false; | 201 return false; |
202 | 202 |
203 // Can't send a message to a child that doesn't exist. | 203 // Can't send a message to a child that doesn't exist. |
204 auto iter = children_.find(render_process_id); | 204 auto iter = children_.find(render_process_id); |
205 if (iter == children_.end()) | 205 if (iter == children_.end()) |
206 return false; | 206 return false; |
207 | 207 |
208 // Can't send a message to a child that isn't bound. | 208 // Can't send a message to a child that isn't bound. |
209 if (!iter->second.handle->child().is_bound()) | 209 if (!iter->second.handle->child().is_bound()) |
210 return false; | 210 return false; |
211 | 211 |
212 memory_state = OverrideGlobalState(memory_state, iter->second); | 212 memory_state = OverrideGlobalState(memory_state, iter->second); |
213 | 213 |
214 // A nop doesn't need to be sent, but is considered successful. | 214 // A nop doesn't need to be sent, but is considered successful. |
215 if (iter->second.memory_state == memory_state) | 215 if (iter->second.memory_state == memory_state) |
216 return true; | 216 return true; |
217 | 217 |
218 // Can't suspend the given renderer. | 218 // Can't suspend the given renderer. |
219 if (memory_state == mojom::MemoryState::SUSPENDED && | 219 if (memory_state == MemoryState::SUSPENDED && |
220 !CanSuspendRenderer(render_process_id)) | 220 !CanSuspendRenderer(render_process_id)) |
221 return false; | 221 return false; |
222 | 222 |
223 // Update the internal state and send the message. | 223 // Update the internal state and send the message. |
224 iter->second.memory_state = memory_state; | 224 iter->second.memory_state = memory_state; |
225 iter->second.handle->child()->OnStateChange(memory_state); | 225 iter->second.handle->child()->OnStateChange(ToMojomMemoryState(memory_state)); |
226 return true; | 226 return true; |
227 } | 227 } |
228 | 228 |
229 mojom::MemoryState MemoryCoordinatorImpl::GetChildMemoryState( | 229 base::MemoryState MemoryCoordinatorImpl::GetChildMemoryState( |
230 int render_process_id) const { | 230 int render_process_id) const { |
231 auto iter = children_.find(render_process_id); | 231 auto iter = children_.find(render_process_id); |
232 if (iter == children_.end()) | 232 if (iter == children_.end()) |
233 return mojom::MemoryState::UNKNOWN; | 233 return base::MemoryState::UNKNOWN; |
234 return iter->second.memory_state; | 234 return iter->second.memory_state; |
235 } | 235 } |
236 | 236 |
237 void MemoryCoordinatorImpl::RecordMemoryPressure( | 237 void MemoryCoordinatorImpl::RecordMemoryPressure( |
238 base::MemoryPressureMonitor::MemoryPressureLevel level) { | 238 base::MemoryPressureMonitor::MemoryPressureLevel level) { |
239 DCHECK(GetGlobalMemoryState() != base::MemoryState::UNKNOWN); | 239 DCHECK(GetGlobalMemoryState() != base::MemoryState::UNKNOWN); |
240 int state = static_cast<int>(GetGlobalMemoryState()); | 240 int state = static_cast<int>(GetGlobalMemoryState()); |
241 switch (level) { | 241 switch (level) { |
242 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: | 242 case base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE: |
243 UMA_HISTOGRAM_ENUMERATION( | 243 UMA_HISTOGRAM_ENUMERATION( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 const NotificationDetails& details) { | 285 const NotificationDetails& details) { |
286 DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED); | 286 DCHECK(type == NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED); |
287 RenderWidgetHost* render_widget_host = Source<RenderWidgetHost>(source).ptr(); | 287 RenderWidgetHost* render_widget_host = Source<RenderWidgetHost>(source).ptr(); |
288 RenderProcessHost* process = render_widget_host->GetProcess(); | 288 RenderProcessHost* process = render_widget_host->GetProcess(); |
289 if (!process) | 289 if (!process) |
290 return; | 290 return; |
291 auto iter = children().find(process->GetID()); | 291 auto iter = children().find(process->GetID()); |
292 if (iter == children().end()) | 292 if (iter == children().end()) |
293 return; | 293 return; |
294 iter->second.is_visible = *Details<bool>(details).ptr(); | 294 iter->second.is_visible = *Details<bool>(details).ptr(); |
295 auto new_state = ToMojomMemoryState(GetGlobalMemoryState()); | 295 auto new_state = GetGlobalMemoryState(); |
296 SetChildMemoryState(iter->first, new_state); | 296 SetChildMemoryState(iter->first, new_state); |
297 } | 297 } |
298 | 298 |
299 bool MemoryCoordinatorImpl::ChangeStateIfNeeded(base::MemoryState prev_state, | 299 bool MemoryCoordinatorImpl::ChangeStateIfNeeded(base::MemoryState prev_state, |
300 base::MemoryState next_state) { | 300 base::MemoryState next_state) { |
301 DCHECK(CalledOnValidThread()); | 301 DCHECK(CalledOnValidThread()); |
302 if (prev_state == next_state) | 302 if (prev_state == next_state) |
303 return false; | 303 return false; |
304 | 304 |
305 base::TimeTicks prev_last_state_change = last_state_change_; | 305 base::TimeTicks prev_last_state_change = last_state_change_; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 auto* render_process_host = RenderProcessHost::FromID(render_process_id); | 338 auto* render_process_host = RenderProcessHost::FromID(render_process_id); |
339 if (!render_process_host || !render_process_host->IsProcessBackgrounded()) | 339 if (!render_process_host || !render_process_host->IsProcessBackgrounded()) |
340 return false; | 340 return false; |
341 if (render_process_host->GetWorkerRefCount() > 0) | 341 if (render_process_host->GetWorkerRefCount() > 0) |
342 return false; | 342 return false; |
343 return delegate_->CanSuspendBackgroundedRenderer(render_process_id); | 343 return delegate_->CanSuspendBackgroundedRenderer(render_process_id); |
344 } | 344 } |
345 | 345 |
346 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) { | 346 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) { |
347 // Populate the global state as an initial state of a newly created process. | 347 // Populate the global state as an initial state of a newly created process. |
348 auto new_state = ToMojomMemoryState(GetGlobalMemoryState()); | 348 auto new_state = GetGlobalMemoryState(); |
349 SetChildMemoryState(render_process_id, new_state); | 349 SetChildMemoryState(render_process_id, new_state); |
350 } | 350 } |
351 | 351 |
352 mojom::MemoryState MemoryCoordinatorImpl::OverrideGlobalState( | 352 base::MemoryState MemoryCoordinatorImpl::OverrideGlobalState( |
353 mojom::MemoryState memory_state, | 353 MemoryState memory_state, |
354 const ChildInfo& child) { | 354 const ChildInfo& child) { |
355 // We don't suspend foreground renderers. Throttle them instead. | 355 // We don't suspend foreground renderers. Throttle them instead. |
356 if (child.is_visible && memory_state == mojom::MemoryState::SUSPENDED) | 356 if (child.is_visible && memory_state == MemoryState::SUSPENDED) |
357 return mojom::MemoryState::THROTTLED; | 357 return MemoryState::THROTTLED; |
358 #if defined(OS_ANDROID) | 358 #if defined(OS_ANDROID) |
359 // On Android, we throttle background renderers immediately. | 359 // On Android, we throttle background renderers immediately. |
360 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android | 360 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android |
361 // and move this ifdef to the class. | 361 // and move this ifdef to the class. |
362 if (!child.is_visible && memory_state == mojom::MemoryState::NORMAL) | 362 if (!child.is_visible && memory_state == MemoryState::NORMAL) |
363 return mojom::MemoryState::THROTTLED; | 363 return MemoryState::THROTTLED; |
364 // TODO(bashi): Suspend background renderers after a certain period of time. | 364 // TODO(bashi): Suspend background renderers after a certain period of time. |
365 #endif // defined(OS_ANDROID) | 365 #endif // defined(OS_ANDROID) |
366 return memory_state; | 366 return memory_state; |
367 } | 367 } |
368 | 368 |
369 void MemoryCoordinatorImpl::SetDelegateForTesting( | 369 void MemoryCoordinatorImpl::SetDelegateForTesting( |
370 std::unique_ptr<MemoryCoordinatorDelegate> delegate) { | 370 std::unique_ptr<MemoryCoordinatorDelegate> delegate) { |
371 CHECK(!delegate_); | 371 CHECK(!delegate_); |
372 delegate_ = std::move(delegate); | 372 delegate_ = std::move(delegate); |
373 } | 373 } |
374 | 374 |
375 void MemoryCoordinatorImpl::CreateChildInfoMapEntry( | 375 void MemoryCoordinatorImpl::CreateChildInfoMapEntry( |
376 int render_process_id, | 376 int render_process_id, |
377 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) { | 377 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) { |
378 auto& child_info = children_[render_process_id]; | 378 auto& child_info = children_[render_process_id]; |
379 // Process always start with normal memory state. | 379 // Process always start with normal memory state. |
380 // We'll set renderer's memory state to the current global state when the | 380 // We'll set renderer's memory state to the current global state when the |
381 // corresponding renderer process is ready to communicate. Renderer processes | 381 // corresponding renderer process is ready to communicate. Renderer processes |
382 // call AddChild() when they are ready. | 382 // call AddChild() when they are ready. |
383 child_info.memory_state = mojom::MemoryState::NORMAL; | 383 child_info.memory_state = MemoryState::NORMAL; |
384 child_info.is_visible = true; | 384 child_info.is_visible = true; |
385 child_info.handle = std::move(handle); | 385 child_info.handle = std::move(handle); |
386 } | 386 } |
387 | 387 |
388 void MemoryCoordinatorImpl::NotifyStateToClients() { | 388 void MemoryCoordinatorImpl::NotifyStateToClients() { |
389 auto state = GetCurrentMemoryState(); | 389 auto state = GetCurrentMemoryState(); |
390 base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(state); | 390 base::MemoryCoordinatorClientRegistry::GetInstance()->Notify(state); |
391 } | 391 } |
392 | 392 |
393 void MemoryCoordinatorImpl::NotifyStateToChildren() { | 393 void MemoryCoordinatorImpl::NotifyStateToChildren() { |
394 auto mojo_state = ToMojomMemoryState(current_state_); | |
395 // It's OK to call SetChildMemoryState() unconditionally because it checks | 394 // It's OK to call SetChildMemoryState() unconditionally because it checks |
396 // whether this state transition is valid. | 395 // whether this state transition is valid. |
397 for (auto& iter : children()) | 396 for (auto& iter : children()) |
398 SetChildMemoryState(iter.first, mojo_state); | 397 SetChildMemoryState(iter.first, current_state_); |
399 } | 398 } |
400 | 399 |
401 void MemoryCoordinatorImpl::RecordStateChange(MemoryState prev_state, | 400 void MemoryCoordinatorImpl::RecordStateChange(MemoryState prev_state, |
402 MemoryState next_state, | 401 MemoryState next_state, |
403 base::TimeDelta duration) { | 402 base::TimeDelta duration) { |
404 size_t total_private_kb = 0; | 403 size_t total_private_kb = 0; |
405 | 404 |
406 // TODO(bashi): On MacOS we can't get process metrics for child processes and | 405 // TODO(bashi): On MacOS we can't get process metrics for child processes and |
407 // therefore can't calculate the total private memory. | 406 // therefore can't calculate the total private memory. |
408 #if !defined(OS_MACOSX) | 407 #if !defined(OS_MACOSX) |
(...skipping 20 matching lines...) Expand all Loading... |
429 | 428 |
430 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {} | 429 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {} |
431 | 430 |
432 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) { | 431 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) { |
433 // This is a nop, but exists for compatibility with STL containers. | 432 // This is a nop, but exists for compatibility with STL containers. |
434 } | 433 } |
435 | 434 |
436 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {} | 435 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {} |
437 | 436 |
438 } // namespace content | 437 } // namespace content |
OLD | NEW |