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 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
309 TRACE_EVENT2("memory-infra", "MemoryCoordinatorImpl::ChangeStateIfNeeded", | 309 TRACE_EVENT2("memory-infra", "MemoryCoordinatorImpl::ChangeStateIfNeeded", |
310 "prev", MemoryStateToString(prev_state), | 310 "prev", MemoryStateToString(prev_state), |
311 "next", MemoryStateToString(next_state)); | 311 "next", MemoryStateToString(next_state)); |
312 RecordStateChange(prev_state, next_state, | 312 RecordStateChange(prev_state, next_state, |
313 last_state_change_ - prev_last_state_change); | 313 last_state_change_ - prev_last_state_change); |
314 NotifyStateToClients(); | 314 NotifyStateToClients(); |
315 NotifyStateToChildren(); | 315 NotifyStateToChildren(); |
316 return true; | 316 return true; |
317 } | 317 } |
318 | 318 |
| 319 RenderProcessHost* MemoryCoordinatorImpl::GetRenderProcessHost( |
| 320 int render_process_id) { |
| 321 return RenderProcessHost::FromID(render_process_id); |
| 322 } |
| 323 |
| 324 void MemoryCoordinatorImpl::SetDelegateForTesting( |
| 325 std::unique_ptr<MemoryCoordinatorDelegate> delegate) { |
| 326 CHECK(!delegate_); |
| 327 delegate_ = std::move(delegate); |
| 328 } |
| 329 |
319 void MemoryCoordinatorImpl::AddChildForTesting( | 330 void MemoryCoordinatorImpl::AddChildForTesting( |
320 int dummy_render_process_id, mojom::ChildMemoryCoordinatorPtr child) { | 331 int dummy_render_process_id, mojom::ChildMemoryCoordinatorPtr child) { |
321 mojom::MemoryCoordinatorHandlePtr mch; | 332 mojom::MemoryCoordinatorHandlePtr mch; |
322 auto request = mojo::GetProxy(&mch); | 333 auto request = mojo::GetProxy(&mch); |
323 std::unique_ptr<MemoryCoordinatorHandleImpl> handle( | 334 std::unique_ptr<MemoryCoordinatorHandleImpl> handle( |
324 new MemoryCoordinatorHandleImpl(std::move(request), this, | 335 new MemoryCoordinatorHandleImpl(std::move(request), this, |
325 dummy_render_process_id)); | 336 dummy_render_process_id)); |
326 handle->AddChild(std::move(child)); | 337 handle->AddChild(std::move(child)); |
327 CreateChildInfoMapEntry(dummy_render_process_id, std::move(handle)); | 338 CreateChildInfoMapEntry(dummy_render_process_id, std::move(handle)); |
328 } | 339 } |
329 | 340 |
330 void MemoryCoordinatorImpl::OnConnectionError(int render_process_id) { | 341 void MemoryCoordinatorImpl::OnConnectionError(int render_process_id) { |
331 children_.erase(render_process_id); | 342 children_.erase(render_process_id); |
332 } | 343 } |
333 | 344 |
334 bool MemoryCoordinatorImpl::CanSuspendRenderer(int render_process_id) { | 345 bool MemoryCoordinatorImpl::CanSuspendRenderer(int render_process_id) { |
335 // If there is no delegate (i.e. unittests), renderers are always suspendable. | 346 auto* render_process_host = GetRenderProcessHost(render_process_id); |
336 if (!delegate_) | |
337 return true; | |
338 auto* render_process_host = RenderProcessHost::FromID(render_process_id); | |
339 if (!render_process_host || !render_process_host->IsProcessBackgrounded()) | 347 if (!render_process_host || !render_process_host->IsProcessBackgrounded()) |
340 return false; | 348 return false; |
341 if (render_process_host->GetWorkerRefCount() > 0) | 349 if (render_process_host->GetWorkerRefCount() > 0) |
342 return false; | 350 return false; |
| 351 // Assumes that we can't suspend renderers if there is no delegate. |
| 352 if (!delegate_) |
| 353 return false; |
343 return delegate_->CanSuspendBackgroundedRenderer(render_process_id); | 354 return delegate_->CanSuspendBackgroundedRenderer(render_process_id); |
344 } | 355 } |
345 | 356 |
346 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) { | 357 void MemoryCoordinatorImpl::OnChildAdded(int render_process_id) { |
347 // Populate the global state as an initial state of a newly created process. | 358 // Populate the global state as an initial state of a newly created process. |
348 auto new_state = GetGlobalMemoryState(); | 359 auto new_state = GetGlobalMemoryState(); |
349 SetChildMemoryState(render_process_id, new_state); | 360 SetChildMemoryState(render_process_id, new_state); |
350 } | 361 } |
351 | 362 |
352 base::MemoryState MemoryCoordinatorImpl::OverrideGlobalState( | 363 base::MemoryState MemoryCoordinatorImpl::OverrideGlobalState( |
353 MemoryState memory_state, | 364 MemoryState memory_state, |
354 const ChildInfo& child) { | 365 const ChildInfo& child) { |
355 // We don't suspend foreground renderers. Throttle them instead. | 366 // We don't suspend foreground renderers. Throttle them instead. |
356 if (child.is_visible && memory_state == MemoryState::SUSPENDED) | 367 if (child.is_visible && memory_state == MemoryState::SUSPENDED) |
357 return MemoryState::THROTTLED; | 368 return MemoryState::THROTTLED; |
358 #if defined(OS_ANDROID) | 369 #if defined(OS_ANDROID) |
359 // On Android, we throttle background renderers immediately. | 370 // On Android, we throttle background renderers immediately. |
360 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android | 371 // TODO(bashi): Create a specialized class of MemoryCoordinator for Android |
361 // and move this ifdef to the class. | 372 // and move this ifdef to the class. |
362 if (!child.is_visible && memory_state == MemoryState::NORMAL) | 373 if (!child.is_visible && memory_state == MemoryState::NORMAL) |
363 return MemoryState::THROTTLED; | 374 return MemoryState::THROTTLED; |
364 // TODO(bashi): Suspend background renderers after a certain period of time. | 375 // TODO(bashi): Suspend background renderers after a certain period of time. |
365 #endif // defined(OS_ANDROID) | 376 #endif // defined(OS_ANDROID) |
366 return memory_state; | 377 return memory_state; |
367 } | 378 } |
368 | 379 |
369 void MemoryCoordinatorImpl::SetDelegateForTesting( | |
370 std::unique_ptr<MemoryCoordinatorDelegate> delegate) { | |
371 CHECK(!delegate_); | |
372 delegate_ = std::move(delegate); | |
373 } | |
374 | |
375 void MemoryCoordinatorImpl::CreateChildInfoMapEntry( | 380 void MemoryCoordinatorImpl::CreateChildInfoMapEntry( |
376 int render_process_id, | 381 int render_process_id, |
377 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) { | 382 std::unique_ptr<MemoryCoordinatorHandleImpl> handle) { |
378 auto& child_info = children_[render_process_id]; | 383 auto& child_info = children_[render_process_id]; |
379 // Process always start with normal memory state. | 384 // Process always start with normal memory state. |
380 // We'll set renderer's memory state to the current global state when the | 385 // We'll set renderer's memory state to the current global state when the |
381 // corresponding renderer process is ready to communicate. Renderer processes | 386 // corresponding renderer process is ready to communicate. Renderer processes |
382 // call AddChild() when they are ready. | 387 // call AddChild() when they are ready. |
383 child_info.memory_state = MemoryState::NORMAL; | 388 child_info.memory_state = MemoryState::NORMAL; |
384 child_info.is_visible = true; | 389 child_info.is_visible = true; |
(...skipping 19 matching lines...) Expand all Loading... |
404 | 409 |
405 // TODO(bashi): On MacOS we can't get process metrics for child processes and | 410 // TODO(bashi): On MacOS we can't get process metrics for child processes and |
406 // therefore can't calculate the total private memory. | 411 // therefore can't calculate the total private memory. |
407 #if !defined(OS_MACOSX) | 412 #if !defined(OS_MACOSX) |
408 auto browser_metrics = base::ProcessMetrics::CreateCurrentProcessMetrics(); | 413 auto browser_metrics = base::ProcessMetrics::CreateCurrentProcessMetrics(); |
409 base::WorkingSetKBytes working_set; | 414 base::WorkingSetKBytes working_set; |
410 browser_metrics->GetWorkingSetKBytes(&working_set); | 415 browser_metrics->GetWorkingSetKBytes(&working_set); |
411 total_private_kb += working_set.priv; | 416 total_private_kb += working_set.priv; |
412 | 417 |
413 for (auto& iter : children()) { | 418 for (auto& iter : children()) { |
414 auto* render_process_host = RenderProcessHost::FromID(iter.first); | 419 auto* render_process_host = GetRenderProcessHost(iter.first); |
415 if (!render_process_host || | 420 if (!render_process_host || |
416 render_process_host->GetHandle() == base::kNullProcessHandle) | 421 render_process_host->GetHandle() == base::kNullProcessHandle) |
417 continue; | 422 continue; |
418 auto metrics = base::ProcessMetrics::CreateProcessMetrics( | 423 auto metrics = base::ProcessMetrics::CreateProcessMetrics( |
419 render_process_host->GetHandle()); | 424 render_process_host->GetHandle()); |
420 metrics->GetWorkingSetKBytes(&working_set); | 425 metrics->GetWorkingSetKBytes(&working_set); |
421 total_private_kb += working_set.priv; | 426 total_private_kb += working_set.priv; |
422 } | 427 } |
423 #endif | 428 #endif |
424 | 429 |
425 RecordMetricsOnStateChange(prev_state, next_state, duration, | 430 RecordMetricsOnStateChange(prev_state, next_state, duration, |
426 total_private_kb / 1024); | 431 total_private_kb / 1024); |
427 } | 432 } |
428 | 433 |
429 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {} | 434 MemoryCoordinatorImpl::ChildInfo::ChildInfo() {} |
430 | 435 |
431 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) { | 436 MemoryCoordinatorImpl::ChildInfo::ChildInfo(const ChildInfo& rhs) { |
432 // This is a nop, but exists for compatibility with STL containers. | 437 // This is a nop, but exists for compatibility with STL containers. |
433 } | 438 } |
434 | 439 |
435 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {} | 440 MemoryCoordinatorImpl::ChildInfo::~ChildInfo() {} |
436 | 441 |
437 } // namespace content | 442 } // namespace content |
OLD | NEW |