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

Side by Side Diff: chrome/browser/memory/tab_manager.cc

Issue 1914143002: Experimental 'purging and suspending' backgrounded tabs behind the flag (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address on haraken's review Created 4 years, 7 months 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
« no previous file with comments | « chrome/browser/memory/tab_manager.h ('k') | chrome/browser/memory/tab_manager_browsertest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "chrome/browser/memory/tab_manager.h" 5 #include "chrome/browser/memory/tab_manager.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <set> 10 #include <set>
(...skipping 23 matching lines...) Expand all
34 #include "chrome/browser/memory/tab_manager_web_contents_data.h" 34 #include "chrome/browser/memory/tab_manager_web_contents_data.h"
35 #include "chrome/browser/profiles/profile.h" 35 #include "chrome/browser/profiles/profile.h"
36 #include "chrome/browser/ui/browser.h" 36 #include "chrome/browser/ui/browser.h"
37 #include "chrome/browser/ui/browser_list.h" 37 #include "chrome/browser/ui/browser_list.h"
38 #include "chrome/browser/ui/browser_window.h" 38 #include "chrome/browser/ui/browser_window.h"
39 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h" 39 #include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
40 #include "chrome/browser/ui/tabs/tab_strip_model.h" 40 #include "chrome/browser/ui/tabs/tab_strip_model.h"
41 #include "chrome/browser/ui/tabs/tab_utils.h" 41 #include "chrome/browser/ui/tabs/tab_utils.h"
42 #include "chrome/common/chrome_constants.h" 42 #include "chrome/common/chrome_constants.h"
43 #include "chrome/common/chrome_features.h" 43 #include "chrome/common/chrome_features.h"
44 #include "chrome/common/chrome_switches.h"
44 #include "chrome/common/url_constants.h" 45 #include "chrome/common/url_constants.h"
45 #include "components/metrics/system_memory_stats_recorder.h" 46 #include "components/metrics/system_memory_stats_recorder.h"
46 #include "components/variations/variations_associated_data.h" 47 #include "components/variations/variations_associated_data.h"
47 #include "content/public/browser/browser_thread.h" 48 #include "content/public/browser/browser_thread.h"
48 #include "content/public/browser/memory_pressure_controller.h" 49 #include "content/public/browser/memory_pressure_controller.h"
49 #include "content/public/browser/navigation_controller.h" 50 #include "content/public/browser/navigation_controller.h"
50 #include "content/public/browser/render_process_host.h" 51 #include "content/public/browser/render_process_host.h"
51 #include "content/public/browser/web_contents.h" 52 #include "content/public/browser/web_contents.h"
52 #include "content/public/common/page_importance_signals.h" 53 #include "content/public/common/page_importance_signals.h"
53 54
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 bool is_active_window = browser->window()->IsActive(); 478 bool is_active_window = browser->window()->IsActive();
478 AddTabStats(browser->tab_strip_model(), browser->is_app(), is_active_window, 479 AddTabStats(browser->tab_strip_model(), browser->is_app(), is_active_window,
479 stats_list); 480 stats_list);
480 } 481 }
481 } 482 }
482 483
483 void TabManager::AddTabStats(const TabStripModel* model, 484 void TabManager::AddTabStats(const TabStripModel* model,
484 bool is_app, 485 bool is_app,
485 bool active_model, 486 bool active_model,
486 TabStatsList* stats_list) { 487 TabStatsList* stats_list) {
487 for (int i = 0; i < model->count(); i++) { 488 for (int i = 0; i < model->count(); i++) {
488 WebContents* contents = model->GetWebContentsAt(i); 489 WebContents* contents = model->GetWebContentsAt(i);
489 if (!contents->IsCrashed()) { 490 if (!contents->IsCrashed()) {
490 TabStats stats; 491 TabStats stats;
491 stats.is_app = is_app; 492 stats.is_app = is_app;
492 stats.is_internal_page = 493 stats.is_internal_page =
493 IsInternalPage(contents->GetLastCommittedURL()); 494 IsInternalPage(contents->GetLastCommittedURL());
494 stats.is_media = IsMediaTab(contents); 495 stats.is_media = IsMediaTab(contents);
495 stats.is_pinned = model->IsTabPinned(i); 496 stats.is_pinned = model->IsTabPinned(i);
496 stats.is_selected = active_model && model->IsTabSelected(i); 497 stats.is_selected = active_model && model->IsTabSelected(i);
497 stats.is_discarded = GetWebContentsData(contents)->IsDiscarded(); 498 stats.is_discarded = GetWebContentsData(contents)->IsDiscarded();
498 stats.has_form_entry = 499 stats.has_form_entry =
499 contents->GetPageImportanceSignals().had_form_interaction; 500 contents->GetPageImportanceSignals().had_form_interaction;
500 stats.discard_count = GetWebContentsData(contents)->DiscardCount(); 501 stats.discard_count = GetWebContentsData(contents)->DiscardCount();
501 stats.last_active = contents->GetLastActiveTime(); 502 stats.last_active = contents->GetLastActiveTime();
502 stats.render_process_host = contents->GetRenderProcessHost(); 503 stats.render_process_host = contents->GetRenderProcessHost();
503 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle(); 504 stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
504 stats.child_process_host_id = contents->GetRenderProcessHost()->GetID(); 505 stats.child_process_host_id = contents->GetRenderProcessHost()->GetID();
505 #if defined(OS_CHROMEOS) 506 #if defined(OS_CHROMEOS)
506 stats.oom_score = delegate_->GetCachedOomScore(stats.renderer_handle); 507 stats.oom_score = delegate_->GetCachedOomScore(stats.renderer_handle);
507 #endif 508 #endif
508 stats.title = contents->GetTitle(); 509 stats.title = contents->GetTitle();
509 stats.tab_contents_id = IdFromWebContents(contents); 510 stats.tab_contents_id = IdFromWebContents(contents);
510 stats_list->push_back(stats); 511 stats_list->push_back(stats);
511 } 512 }
512 } 513 }
513 } 514 }
514 515
515 // This function is called when |update_timer_| fires. It will adjust the clock 516 // This function is called when |update_timer_| fires. It will adjust the clock
516 // if needed (if it detects that the machine was asleep) and will fire the stats 517 // if needed (if it detects that the machine was asleep) and will fire the stats
517 // updating on ChromeOS via the delegate. 518 // updating on ChromeOS via the delegate. This function also tries to purge
519 // cache memory and suspend tabs which becomes and keeps backgrounded for a
520 // while.
518 void TabManager::UpdateTimerCallback() { 521 void TabManager::UpdateTimerCallback() {
519 // If Chrome is shutting down, do not do anything. 522 // If Chrome is shutting down, do not do anything.
520 if (g_browser_process->IsShuttingDown()) 523 if (g_browser_process->IsShuttingDown())
521 return; 524 return;
522 525
523 if (BrowserList::GetInstance()->empty()) 526 if (BrowserList::GetInstance()->empty())
524 return; 527 return;
525 528
526 // Check for a discontinuity in time caused by the machine being suspended. 529 // Check for a discontinuity in time caused by the machine being suspended.
527 if (!last_adjust_time_.is_null()) { 530 if (!last_adjust_time_.is_null()) {
528 TimeDelta suspend_time = NowTicks() - last_adjust_time_; 531 TimeDelta suspend_time = NowTicks() - last_adjust_time_;
529 if (suspend_time.InSeconds() > kSuspendThresholdSeconds) { 532 if (suspend_time.InSeconds() > kSuspendThresholdSeconds) {
530 // System was probably suspended, move the event timers forward in time so 533 // System was probably suspended, move the event timers forward in time so
531 // when they get subtracted out later, "uptime" is being counted. 534 // when they get subtracted out later, "uptime" is being counted.
532 start_time_ += suspend_time; 535 start_time_ += suspend_time;
533 if (!last_discard_time_.is_null()) 536 if (!last_discard_time_.is_null())
534 last_discard_time_ += suspend_time; 537 last_discard_time_ += suspend_time;
535 } 538 }
536 } 539 }
537 last_adjust_time_ = NowTicks(); 540 last_adjust_time_ = NowTicks();
538 541
539 #if defined(OS_CHROMEOS) 542 #if defined(OS_CHROMEOS)
540 TabStatsList stats_list = GetTabStats(); 543 TabStatsList stats_list = GetTabStats();
541 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. 544 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj.
542 delegate_->AdjustOomPriorities(stats_list); 545 delegate_->AdjustOomPriorities(stats_list);
543 #endif 546 #endif
547
548 PurgeAndSuspendBackgroundedTabs();
549 }
550
551 void TabManager::PurgeAndSuspendBackgroundedTabs() {
552 const base::CommandLine& command_line =
553 *base::CommandLine::ForCurrentProcess();
554 if (!command_line.HasSwitch(switches::kPurgeAndSuspendTime))
555 return;
556 int purge_and_suspend_time = 0;
557 if (!base::StringToInt(
558 command_line.GetSwitchValueASCII(switches::kPurgeAndSuspendTime),
559 &purge_and_suspend_time)) {
560 return;
561 }
562 if (purge_and_suspend_time <= 0)
563 return;
564 auto purge_and_suspend_time_threshold = NowTicks() -
565 base::TimeDelta::FromSeconds(purge_and_suspend_time);
566 auto tab_stats = GetUnsortedTabStats();
567 for (auto& tab : tab_stats) {
568 if (!tab.render_process_host->IsProcessBackgrounded())
569 continue;
570 // TODO(hajimehoshi): Now calling PurgeAndSuspend is implemented without
571 // timers for simplicity, so PurgeAndSuspend is called even after the
572 // renderer is purged and suspended once. This should be replaced with
573 // timers if we want necessary and sufficient signals.
574 if (tab.last_active > purge_and_suspend_time_threshold)
575 continue;
576 tab.render_process_host->PurgeAndSuspend();
577 }
544 } 578 }
545 579
546 bool TabManager::CanDiscardTab(int64_t target_web_contents_id) const { 580 bool TabManager::CanDiscardTab(int64_t target_web_contents_id) const {
547 TabStripModel* model; 581 TabStripModel* model;
548 int idx = FindTabStripModelById(target_web_contents_id, &model); 582 int idx = FindTabStripModelById(target_web_contents_id, &model);
549 583
550 if (idx == -1) 584 if (idx == -1)
551 return false; 585 return false;
552 586
553 WebContents* web_contents = model->GetWebContentsAt(idx); 587 WebContents* web_contents = model->GetWebContentsAt(idx);
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
844 } 878 }
845 } else { 879 } else {
846 // The code here can only be tested under a full browser test. 880 // The code here can only be tested under a full browser test.
847 AddTabStats(&stats_list); 881 AddTabStats(&stats_list);
848 } 882 }
849 883
850 return stats_list; 884 return stats_list;
851 } 885 }
852 886
853 } // namespace memory 887 } // namespace memory
OLDNEW
« no previous file with comments | « chrome/browser/memory/tab_manager.h ('k') | chrome/browser/memory/tab_manager_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698