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

Unified Diff: chrome/browser/memory/tab_manager_delegate_chromeos.cc

Issue 2095413002: TabManagerDelegate: Better prioritize ARC processes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 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
Index: chrome/browser/memory/tab_manager_delegate_chromeos.cc
diff --git a/chrome/browser/memory/tab_manager_delegate_chromeos.cc b/chrome/browser/memory/tab_manager_delegate_chromeos.cc
index 482efe35c44111ba25b9837e121bd96f85e14e03..0042182f527b58c509aef7b779185e245c224b53 100644
--- a/chrome/browser/memory/tab_manager_delegate_chromeos.cc
+++ b/chrome/browser/memory/tab_manager_delegate_chromeos.cc
@@ -75,65 +75,6 @@ bool IsArcWindow(aura::Window* window) {
return application_id.find(kArcProcessNamePrefix) == 0;
}
-bool IsArcWindowInForeground() {
- auto activation_client = GetActivationClient();
- return activation_client && IsArcWindow(activation_client->GetActiveWindow());
-}
-
-int AppStateToPriority(
- const arc::mojom::ProcessState& process_state) {
- // Logic copied from Android:
- // frameworks/base/core/java/android/app/ActivityManager.java
- // Note that ProcessState enumerates from most important (lower value) to
- // least important (higher value), while ProcessPriority enumerates the
- // opposite.
- if (process_state >= arc::mojom::ProcessState::HOME) {
- return ProcessPriority::ANDROID_BACKGROUND;
- } else if (process_state >= arc::mojom::ProcessState::SERVICE) {
- return ProcessPriority::ANDROID_SERVICE;
- } else if (process_state >= arc::mojom::ProcessState::HEAVY_WEIGHT) {
- return ProcessPriority::ANDROID_CANT_SAVE_STATE;
- } else if (process_state >= arc::mojom::ProcessState::IMPORTANT_BACKGROUND) {
- return ProcessPriority::ANDROID_PERCEPTIBLE;
- } else if (process_state >= arc::mojom::ProcessState::IMPORTANT_FOREGROUND) {
- return ProcessPriority::ANDROID_VISIBLE;
- } else if (process_state >= arc::mojom::ProcessState::TOP_SLEEPING) {
- return ProcessPriority::ANDROID_TOP_SLEEPING;
- } else if (process_state >= arc::mojom::ProcessState::FOREGROUND_SERVICE) {
- return ProcessPriority::ANDROID_FOREGROUND_SERVICE;
- } else if (process_state >= arc::mojom::ProcessState::TOP) {
- return IsArcWindowInForeground() ?
- ProcessPriority::ANDROID_TOP :
- ProcessPriority::ANDROID_TOP_INACTIVE;
- } else if (process_state >= arc::mojom::ProcessState::PERSISTENT) {
- return ProcessPriority::ANDROID_PERSISTENT;
- }
- return ProcessPriority::ANDROID_NON_EXISTS;
-}
-
-int TabStatsToPriority(const TabStats& tab) {
- if (tab.is_selected)
- return ProcessPriority::CHROME_SELECTED;
-
- int priority = 0;
-
- if (tab.is_app) {
- priority = ProcessPriority::CHROME_APP;
- } else if (tab.is_internal_page) {
- priority = ProcessPriority::CHROME_INTERNAL;
- } else {
- priority = ProcessPriority::CHROME_NORMAL;
- }
- if (tab.is_pinned)
- priority |= ProcessPriority::CHROME_PINNED;
- if (tab.is_media)
- priority |= ProcessPriority::CHROME_MEDIA;
- if (tab.has_form_entry)
- priority |= ProcessPriority::CHROME_CANT_SAVE_STATE;
-
- return priority;
-}
-
bool IsArcMemoryManagementEnabled() {
return base::FeatureList::IsEnabled(features::kArcMemoryManagement);
}
@@ -142,13 +83,15 @@ bool IsArcMemoryManagementEnabled() {
std::ostream& operator<<(
std::ostream& out, const TabManagerDelegate::Candidate& candidate) {
- if (candidate.is_arc_app) {
- out << "app " << candidate.app->pid()
- << " (" << candidate.app->process_name() << ")";
- } else {
- out << "tab " << candidate.tab->renderer_handle;
+ if (candidate.app()) {
+ out << "app " << candidate.app()->pid()
+ << " (" << candidate.app()->process_name() << ")"
+ << ", adj " << candidate.app()->adj()
+ << ", lastActivityTime " << candidate.app()->last_activity_time();
+ } else if (candidate.tab()) {
+ out << "tab " << candidate.tab()->renderer_handle;
}
- out << " with priority " << candidate.priority;
+ out << ", process_type " << candidate.process_type();
return out;
}
@@ -284,15 +227,15 @@ int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB(
}
class TabManagerDelegate::UmaReporter {
- public:
- UmaReporter()
- : last_kill_time_(), total_kills_(0) {}
- ~UmaReporter() {}
- void ReportKill(const int memory_freed);
-
- private:
- base::Time last_kill_time_;
- int total_kills_;
+ public:
+ UmaReporter()
+ : last_kill_time_(), total_kills_(0) {}
+ ~UmaReporter() {}
+ void ReportKill(const int memory_freed);
+
+ private:
+ base::Time last_kill_time_;
+ int total_kills_;
};
void TabManagerDelegate::UmaReporter::ReportKill(const int memory_freed) {
@@ -404,6 +347,10 @@ void TabManagerDelegate::OnProcessInstanceClosed() {
arc_process_instance_version_ = 0;
}
+// TODO(cylee): Remove this function if Android process OOM score settings
+// is moved back to Android.
+// For example, negotiate non-overlapping OOM score ranges so Chrome and Android
+// can set OOM score for processes in their own world.
void TabManagerDelegate::OnWindowActivated(
aura::client::ActivationChangeObserver::ActivationReason reason,
aura::Window* gained_active,
@@ -597,32 +544,37 @@ void TabManagerDelegate::AdjustOomPriorities(const TabStatsList& tab_list) {
}
// Excludes persistent ARC apps, but still preserves active chrome tabs and
-// top ARC apps. The latter ones should not be killed by TabManager since
-// we still want to adjust their oom_score_adj.
+// focused ARC apps. The latter ones should not be killed by TabManager here,
+// but we want to adjust their oom_score_adj.
// static
std::vector<TabManagerDelegate::Candidate>
TabManagerDelegate::GetSortedCandidates(
const TabStatsList& tab_list,
const std::vector<arc::ArcProcess>& arc_processes) {
+ static const char kAppLauncherProcessName[] = "org.chromium.arc.applauncher";
+
std::vector<Candidate> candidates;
candidates.reserve(tab_list.size() + arc_processes.size());
for (const auto& tab : tab_list) {
- candidates.push_back(Candidate(&tab, TabStatsToPriority(tab)));
+ candidates.push_back(Candidate(&tab));
}
for (const auto& app : arc_processes) {
- Candidate candidate(&app, AppStateToPriority(app.process_state()));
- // Skip persistent android processes since we should never kill them.
- // Also don't ajust OOM score so their score remains min oom_score_adj.
- if (candidate.priority >= ProcessPriority::ANDROID_PERSISTENT)
+ // Persistent an system android processes has negative adj value.
+ // Skip them since they should never be killed here. Also don't ajust
+ // OOM score so their score remains min oom_score_adj.
+ //
+ // AppLauncher is treated specially in ARC++. For example it is taken
+ // as the dummy foreground app from Android's point of view when the focused
+ // window is not an Android app. We prefer never kill it.
+ if (app.adj() < 0 || app.process_name() == kAppLauncherProcessName)
continue;
- candidates.push_back(candidate);
+ candidates.push_back(Candidate(&app));
}
// Sort candidates according to priority.
- // TODO(cylee): Missing LRU property. Fix it when apps has the information.
std::sort(candidates.begin(), candidates.end());
return candidates;
@@ -647,37 +599,41 @@ void TabManagerDelegate::LowMemoryKillImpl(
const std::vector<arc::ArcProcess>& arc_processes) {
VLOG(2) << "LowMemoryKilleImpl";
- std::vector<TabManagerDelegate::Candidate> candidates =
+ const std::vector<TabManagerDelegate::Candidate> candidates =
GetSortedCandidates(tab_list, arc_processes);
int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB();
- for (const auto& entry : candidates) {
+ // Kill processes until the estimated amount of freed memory is sufficient to
+ // bring the system memory back to a normal level.
+ // The list is sorted by importance descendingly, so we go through the list
+ // backwards.
+ for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) {
VLOG(3) << "Target memory to free: " << target_memory_to_free_kb << " KB";
// Never kill selected tab or Android foreground app, regardless whether
// they're in the active window. Since the user experience would be bad.
- if ((!entry.is_arc_app &&
- entry.priority >= ProcessPriority::CHROME_SELECTED) ||
- (entry.is_arc_app &&
- entry.priority >= ProcessPriority::ANDROID_TOP_INACTIVE)) {
- VLOG(2) << "Skipped killing " << entry;
+ ProcessType process_type = it->process_type();
+ if (process_type == ProcessType::VISIBLE_APP ||
+ process_type == ProcessType::FOCUSED_APP ||
+ process_type == ProcessType::FOCUSED_TAB) {
+ VLOG(2) << "Skipped killing " << *it;
continue;
}
- if (entry.is_arc_app) {
+ if (it->app()) {
int estimated_memory_freed_kb =
- mem_stat_->EstimatedMemoryFreedKB(entry.app->pid());
- if (KillArcProcess(entry.app->nspid())) {
+ mem_stat_->EstimatedMemoryFreedKB(it->app()->pid());
+ if (KillArcProcess(it->app()->nspid())) {
target_memory_to_free_kb -= estimated_memory_freed_kb;
uma_->ReportKill(estimated_memory_freed_kb);
- VLOG(2) << "Killed " << entry;
+ VLOG(2) << "Killed " << *it;
}
} else {
- int64_t tab_id = entry.tab->tab_contents_id;
+ int64_t tab_id = it->tab()->tab_contents_id;
int estimated_memory_freed_kb =
- mem_stat_->EstimatedMemoryFreedKB(entry.tab->renderer_handle);
+ mem_stat_->EstimatedMemoryFreedKB(it->tab()->renderer_handle);
if (KillTab(tab_id)) {
target_memory_to_free_kb -= estimated_memory_freed_kb;
uma_->ReportKill(estimated_memory_freed_kb);
- VLOG(2) << "Killed " << entry;
+ VLOG(2) << "Killed " << *it;
}
}
if (target_memory_to_free_kb < 0)
@@ -689,7 +645,7 @@ void TabManagerDelegate::AdjustOomPrioritiesImpl(
const TabStatsList& tab_list,
const std::vector<arc::ArcProcess>& arc_processes) {
// Least important first.
- auto candidates = GetSortedCandidates(tab_list, arc_processes);
+ const auto candidates = GetSortedCandidates(tab_list, arc_processes);
// Now we assign priorities based on the sorted list. We're assigning
// priorities in the range of kLowestRendererOomScore to
@@ -709,10 +665,9 @@ void TabManagerDelegate::AdjustOomPrioritiesImpl(
// Find some pivot point. For now processes with priority >= CHROME_INTERNAL
// are prone to be affected by LRU change. Taking them as "high priority"
// processes.
- auto lower_priority_part = candidates.rend();
- // Iterate in reverse order since the list is sorted by least importance.
- for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) {
- if (it->priority < ProcessPriority::CHROME_INTERNAL) {
+ auto lower_priority_part = candidates.end();
+ for (auto it = candidates.begin(); it != candidates.end(); ++it) {
+ if (it->process_type() >= ProcessType::BACKGROUND_APP) {
lower_priority_part = it;
break;
}
@@ -721,11 +676,11 @@ void TabManagerDelegate::AdjustOomPrioritiesImpl(
ProcessScoreMap new_map;
// Higher priority part.
- DistributeOomScoreInRange(candidates.rbegin(), lower_priority_part,
+ DistributeOomScoreInRange(candidates.begin(), lower_priority_part,
chrome::kLowestRendererOomScore, range_middle,
&new_map);
// Lower priority part.
- DistributeOomScoreInRange(lower_priority_part, candidates.rend(),
+ DistributeOomScoreInRange(lower_priority_part, candidates.end(),
range_middle, chrome::kHighestRendererOomScore,
&new_map);
base::AutoLock oom_score_autolock(oom_score_lock_);
@@ -761,8 +716,8 @@ void TabManagerDelegate::SetOomScoreAdjForTabsOnFileThread(
}
void TabManagerDelegate::DistributeOomScoreInRange(
- std::vector<TabManagerDelegate::Candidate>::reverse_iterator rbegin,
- std::vector<TabManagerDelegate::Candidate>::reverse_iterator rend,
+ std::vector<TabManagerDelegate::Candidate>::const_iterator begin,
+ std::vector<TabManagerDelegate::Candidate>::const_iterator end,
int range_begin,
int range_end,
ProcessScoreMap* new_map) {
@@ -773,27 +728,27 @@ void TabManagerDelegate::DistributeOomScoreInRange(
// Though there might be duplicate process handles, it doesn't matter to
// overestimate the number of processes here since the we don't need to
// use up the full range.
- int num = (rend - rbegin);
+ int num = (end - begin);
const float priority_increment =
static_cast<float>(range_end - range_begin) / num;
float priority = range_begin;
- for (auto cur = rbegin; cur != rend; ++cur) {
+ for (auto cur = begin; cur != end; ++cur) {
int score = static_cast<int>(priority + 0.5f);
- if (cur->is_arc_app) {
+ if (cur->app()) {
// Use pid as map keys so it's globally unique.
- (*new_map)[cur->app->pid()] = score;
+ (*new_map)[cur->app()->pid()] = score;
int cur_app_pid_score = 0;
{
base::AutoLock oom_score_autolock(oom_score_lock_);
- cur_app_pid_score = oom_score_map_[cur->app->pid()];
+ cur_app_pid_score = oom_score_map_[cur->app()->pid()];
}
if (cur_app_pid_score != score) {
VLOG(3) << "Set OOM score " << score << " for " << *cur;
- SetOomScoreAdjForApp(cur->app->nspid(), score);
+ SetOomScoreAdjForApp(cur->app()->nspid(), score);
}
} else {
- base::ProcessHandle process_handle = cur->tab->renderer_handle;
+ base::ProcessHandle process_handle = cur->tab()->renderer_handle;
// 1. tab_list contains entries for already-discarded tabs. If the PID
// (renderer_handle) is zero, we don't need to adjust the oom_score.
// 2. Only add unseen process handle so if there's multiple tab maps to

Powered by Google App Engine
This is Rietveld 408576698