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

Unified Diff: chrome/browser/oom_priority_manager.cc

Issue 7983042: CrOS: Add Discard Tab command link to about:discards (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: revert tab_strip_model.h Created 9 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/oom_priority_manager.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/oom_priority_manager.cc
diff --git a/chrome/browser/oom_priority_manager.cc b/chrome/browser/oom_priority_manager.cc
index 182cbac09aaaed4f5e1f2806e6d77699cedab131..fb46fc7f3317b60a9ecee1f188b98d3109a2a915 100644
--- a/chrome/browser/oom_priority_manager.cc
+++ b/chrome/browser/oom_priority_manager.cc
@@ -9,10 +9,12 @@
#include "base/process.h"
#include "base/process_util.h"
+#include "base/string_number_conversions.h"
#include "base/string16.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/timer.h"
+#include "base/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/ui/browser_list.h"
@@ -23,6 +25,7 @@
#include "content/browser/renderer_host/render_widget_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/zygote_host_linux.h"
+#include "content/common/content_notification_types.h"
#include "content/common/notification_service.h"
#if !defined(OS_CHROMEOS)
@@ -34,33 +37,38 @@ using base::TimeTicks;
using base::ProcessHandle;
using base::ProcessMetrics;
+namespace {
+
+// Returns a unique ID for a TabContents. Do not cast back to a pointer, as
+// the TabContents could be deleted if the user closed the tab.
+int64 IdFromTabContents(TabContents* tab_contents) {
+ return reinterpret_cast<int64>(tab_contents);
+}
+
+} // namespace
+
namespace browser {
// The default interval in seconds after which to adjust the oom_score_adj
// value.
#define ADJUSTMENT_INTERVAL_SECONDS 10
-// The default interval in minutes for considering activation times
-// "equal".
-#define BUCKET_INTERVAL_MINUTES 10
-
// The default interval in milliseconds to wait before setting the score of
// currently focused tab.
#define FOCUSED_TAB_SCORE_ADJUST_INTERVAL_MS 500
-OomPriorityManager::RendererStats::RendererStats()
+OomPriorityManager::TabStats::TabStats()
: is_pinned(false),
is_selected(false),
- memory_used(0),
- renderer_handle(0) {
+ renderer_handle(0),
+ tab_contents_id(0) {
}
-OomPriorityManager::RendererStats::~RendererStats() {
+OomPriorityManager::TabStats::~TabStats() {
}
OomPriorityManager::OomPriorityManager()
: focused_tab_pid_(0) {
- renderer_stats_.reserve(32); // 99% of users have < 30 tabs open
registrar_.Add(this,
content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
NotificationService::AllSources());
@@ -90,25 +98,48 @@ void OomPriorityManager::Stop() {
}
std::vector<string16> OomPriorityManager::GetTabTitles() {
- base::AutoLock renderer_stats_autolock(renderer_stats_lock_);
+ TabStatsList stats = GetTabStatsOnUIThread();
+ base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
std::vector<string16> titles;
- titles.reserve(renderer_stats_.size());
- StatsList::iterator it = renderer_stats_.begin();
- for ( ; it != renderer_stats_.end(); ++it) {
- titles.push_back(it->title);
+ titles.reserve(stats.size());
+ TabStatsList::iterator it = stats.begin();
+ for ( ; it != stats.end(); ++it) {
+ string16 str = it->title;
+ str += ASCIIToUTF16(" (");
+ int score = pid_to_oom_score_[it->renderer_handle];
+ str += base::IntToString16(score);
+ str += ASCIIToUTF16(")");
+ titles.push_back(str);
}
return titles;
}
+void OomPriorityManager::DiscardTab() {
+ TabStatsList stats = GetTabStatsOnUIThread();
+ if (stats.empty())
+ return;
+ std::sort(stats.begin(), stats.end(), CompareTabStats);
+ TabStatsList::const_reverse_iterator rit = stats.rbegin();
+ int64 least_important_tab_id = rit->tab_contents_id;
+ for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
+ browser_iterator != BrowserList::end(); ++browser_iterator) {
+ Browser* browser = *browser_iterator;
+ TabStripModel* model = browser->tabstrip_model();
+ for (int idx = 0; idx < model->count(); idx++) {
+ TabContents* tab_contents = model->GetTabContentsAt(idx)->tab_contents();
+ int64 tab_contents_id = IdFromTabContents(tab_contents);
+ if (tab_contents_id == least_important_tab_id) {
+ model->CloseTabContentsAt(idx,
+ TabStripModel::CLOSE_CREATE_HISTORICAL_TAB);
+ }
+ }
+ }
+}
+
// Returns true if |first| is considered less desirable to be killed
// than |second|.
-bool OomPriorityManager::CompareRendererStats(RendererStats first,
- RendererStats second) {
- // The size of the slop in comparing activation times. [This is
- // allocated here to avoid static initialization at startup time.]
- static const int64 kTimeBucketInterval =
- TimeDelta::FromMinutes(BUCKET_INTERVAL_MINUTES).ToInternalValue();
-
+bool OomPriorityManager::CompareTabStats(TabStats first,
+ TabStats second) {
// Being currently selected is most important.
if (first.is_selected != second.is_selected)
return first.is_selected == true;
@@ -117,18 +148,12 @@ bool OomPriorityManager::CompareRendererStats(RendererStats first,
if (first.is_pinned != second.is_pinned)
return first.is_pinned == true;
- // We want to be a little "fuzzy" when we compare these, because
- // it's not really possible for the times to be identical, but if
- // the user selected two tabs at about the same time, we still want
- // to take the one that uses more memory.
- if (abs((first.last_selected - second.last_selected).ToInternalValue()) <
- kTimeBucketInterval)
- return first.last_selected > second.last_selected;
-
- return first.memory_used < second.memory_used;
+ // Being more recently selected is more important.
+ return first.last_selected > second.last_selected;
}
-void OomPriorityManager::AdjustFocusedTabScore() {
+void OomPriorityManager::AdjustFocusedTabScoreOnFileThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
ZygoteHost::GetInstance()->AdjustRendererOOMScore(
focused_tab_pid_, chrome::kLowestRendererOomScore);
@@ -138,11 +163,12 @@ void OomPriorityManager::AdjustFocusedTabScore() {
void OomPriorityManager::OnFocusTabScoreAdjustmentTimeout() {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &OomPriorityManager::AdjustFocusedTabScore));
+ NewRunnableMethod(
+ this, &OomPriorityManager::AdjustFocusedTabScoreOnFileThread));
}
void OomPriorityManager::Observe(int type, const NotificationSource& source,
- const NotificationDetails& details) {
+ const NotificationDetails& details) {
base::ProcessHandle handle = 0;
base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
switch (type) {
@@ -193,71 +219,49 @@ void OomPriorityManager::Observe(int type, const NotificationSource& source,
// 1) whether or not a tab is pinned
// 2) last time a tab was selected
// 3) is the tab currently selected
-//
-// We also need to collect:
-// 4) size in memory of a tab
-// But we do that in DoAdjustOomPriorities on the FILE thread so that
-// we avoid jank, because it accesses /proc.
void OomPriorityManager::AdjustOomPriorities() {
if (BrowserList::size() == 0)
return;
+ TabStatsList stats_list = GetTabStatsOnUIThread();
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ NewRunnableMethod(this,
+ &OomPriorityManager::AdjustOomPrioritiesOnFileThread,
+ stats_list));
+}
- {
- base::AutoLock renderer_stats_autolock(renderer_stats_lock_);
- renderer_stats_.clear();
- for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
- browser_iterator != BrowserList::end(); ++browser_iterator) {
- Browser* browser = *browser_iterator;
- const TabStripModel* model = browser->tabstrip_model();
- for (int i = 0; i < model->count(); i++) {
- TabContents* contents = model->GetTabContentsAt(i)->tab_contents();
- if (!contents->is_crashed()) {
- RendererStats stats;
- stats.last_selected = contents->last_selected_time();
- stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
- stats.is_pinned = model->IsTabPinned(i);
- stats.memory_used = 0; // Calculated in DoAdjustOomPriorities.
- stats.is_selected = model->IsTabSelected(i);
- stats.title = contents->GetTitle();
- renderer_stats_.push_back(stats);
- }
+OomPriorityManager::TabStatsList OomPriorityManager::GetTabStatsOnUIThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ TabStatsList stats_list;
+ stats_list.reserve(32); // 99% of users have < 30 tabs open
+ for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
+ browser_iterator != BrowserList::end(); ++browser_iterator) {
+ Browser* browser = *browser_iterator;
+ const TabStripModel* model = browser->tabstrip_model();
+ for (int i = 0; i < model->count(); i++) {
+ TabContents* contents = model->GetTabContentsAt(i)->tab_contents();
+ if (!contents->is_crashed()) {
+ TabStats stats;
+ stats.last_selected = contents->last_selected_time();
+ stats.renderer_handle = contents->GetRenderProcessHost()->GetHandle();
+ stats.is_pinned = model->IsTabPinned(i);
+ stats.is_selected = model->IsTabSelected(i);
+ stats.title = contents->GetTitle();
+ stats.tab_contents_id = IdFromTabContents(contents);
+ stats_list.push_back(stats);
}
}
}
-
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- NewRunnableMethod(this, &OomPriorityManager::DoAdjustOomPriorities));
+ // Sort the data we collected so that least desirable to be
+ // killed is first, most desirable is last.
+ std::sort(stats_list.begin(), stats_list.end(), CompareTabStats);
+ return stats_list;
}
-void OomPriorityManager::DoAdjustOomPriorities() {
+void OomPriorityManager::AdjustOomPrioritiesOnFileThread(
+ TabStatsList stats_list) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- base::AutoLock renderer_stats_autolock(renderer_stats_lock_);
base::AutoLock pid_to_oom_score_autolock(pid_to_oom_score_lock_);
- for (StatsList::iterator stats_iter = renderer_stats_.begin();
- stats_iter != renderer_stats_.end(); ++stats_iter) {
- scoped_ptr<ProcessMetrics> metrics(ProcessMetrics::CreateProcessMetrics(
- stats_iter->renderer_handle));
-
- base::WorkingSetKBytes working_set_kbytes;
- if (metrics->GetWorkingSetKBytes(&working_set_kbytes)) {
- // We use the proportional set size (PSS) to calculate memory
- // usage "badness" on Linux.
- stats_iter->memory_used = working_set_kbytes.shared * 1024;
- } else {
- // and if for some reason we can't get PSS, we revert to using
- // resident set size (RSS). This will be zero if the process
- // has already gone away, but we can live with that, since the
- // process is gone anyhow.
- stats_iter->memory_used = metrics->GetWorkingSetSize();
- }
- }
-
- // Now we sort the data we collected so that least desirable to be
- // killed is first, most desirable is last.
- std::sort(renderer_stats_.begin(),
- renderer_stats_.end(),
- OomPriorityManager::CompareRendererStats);
// Now we assign priorities based on the sorted list. We're
// assigning priorities in the range of kLowestRendererOomScore to
@@ -277,13 +281,13 @@ void OomPriorityManager::DoAdjustOomPriorities() {
const int kPriorityRange = chrome::kHighestRendererOomScore -
chrome::kLowestRendererOomScore;
float priority_increment =
- static_cast<float>(kPriorityRange) / renderer_stats_.size();
+ static_cast<float>(kPriorityRange) / stats_list.size();
float priority = chrome::kLowestRendererOomScore;
std::set<base::ProcessHandle> already_seen;
int score = 0;
ProcessScoreMap::iterator it;
- for (StatsList::iterator iterator = renderer_stats_.begin();
- iterator != renderer_stats_.end(); ++iterator) {
+ for (TabStatsList::iterator iterator = stats_list.begin();
+ iterator != stats_list.end(); ++iterator) {
if (already_seen.find(iterator->renderer_handle) == already_seen.end()) {
already_seen.insert(iterator->renderer_handle);
// If a process has the same score as the newly calculated value,
« no previous file with comments | « chrome/browser/oom_priority_manager.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698