Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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_delegate_chromeos.h" | 5 #include "chrome/browser/memory/tab_manager_delegate_chromeos.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 68 } | 68 } |
| 69 | 69 |
| 70 // Checks if a window renders ARC apps. | 70 // Checks if a window renders ARC apps. |
| 71 bool IsArcWindow(aura::Window* window) { | 71 bool IsArcWindow(aura::Window* window) { |
| 72 if (!window || window->name() != kExoShellSurfaceWindowName) | 72 if (!window || window->name() != kExoShellSurfaceWindowName) |
| 73 return false; | 73 return false; |
| 74 std::string application_id = exo::ShellSurface::GetApplicationId(window); | 74 std::string application_id = exo::ShellSurface::GetApplicationId(window); |
| 75 return application_id.find(kArcProcessNamePrefix) == 0; | 75 return application_id.find(kArcProcessNamePrefix) == 0; |
| 76 } | 76 } |
| 77 | 77 |
| 78 bool IsArcWindowInForeground() { | |
| 79 auto activation_client = GetActivationClient(); | |
| 80 return activation_client && IsArcWindow(activation_client->GetActiveWindow()); | |
| 81 } | |
| 82 | |
| 83 int AppStateToPriority( | |
| 84 const arc::mojom::ProcessState& process_state) { | |
| 85 // Logic copied from Android: | |
| 86 // frameworks/base/core/java/android/app/ActivityManager.java | |
| 87 // Note that ProcessState enumerates from most important (lower value) to | |
| 88 // least important (higher value), while ProcessPriority enumerates the | |
| 89 // opposite. | |
| 90 if (process_state >= arc::mojom::ProcessState::HOME) { | |
| 91 return ProcessPriority::ANDROID_BACKGROUND; | |
| 92 } else if (process_state >= arc::mojom::ProcessState::SERVICE) { | |
| 93 return ProcessPriority::ANDROID_SERVICE; | |
| 94 } else if (process_state >= arc::mojom::ProcessState::HEAVY_WEIGHT) { | |
| 95 return ProcessPriority::ANDROID_CANT_SAVE_STATE; | |
| 96 } else if (process_state >= arc::mojom::ProcessState::IMPORTANT_BACKGROUND) { | |
| 97 return ProcessPriority::ANDROID_PERCEPTIBLE; | |
| 98 } else if (process_state >= arc::mojom::ProcessState::IMPORTANT_FOREGROUND) { | |
| 99 return ProcessPriority::ANDROID_VISIBLE; | |
| 100 } else if (process_state >= arc::mojom::ProcessState::TOP_SLEEPING) { | |
| 101 return ProcessPriority::ANDROID_TOP_SLEEPING; | |
| 102 } else if (process_state >= arc::mojom::ProcessState::FOREGROUND_SERVICE) { | |
| 103 return ProcessPriority::ANDROID_FOREGROUND_SERVICE; | |
| 104 } else if (process_state >= arc::mojom::ProcessState::TOP) { | |
| 105 return IsArcWindowInForeground() ? | |
| 106 ProcessPriority::ANDROID_TOP : | |
| 107 ProcessPriority::ANDROID_TOP_INACTIVE; | |
| 108 } else if (process_state >= arc::mojom::ProcessState::PERSISTENT) { | |
| 109 return ProcessPriority::ANDROID_PERSISTENT; | |
| 110 } | |
| 111 return ProcessPriority::ANDROID_NON_EXISTS; | |
| 112 } | |
| 113 | |
| 114 int TabStatsToPriority(const TabStats& tab) { | |
| 115 if (tab.is_selected) | |
| 116 return ProcessPriority::CHROME_SELECTED; | |
| 117 | |
| 118 int priority = 0; | |
| 119 | |
| 120 if (tab.is_app) { | |
| 121 priority = ProcessPriority::CHROME_APP; | |
| 122 } else if (tab.is_internal_page) { | |
| 123 priority = ProcessPriority::CHROME_INTERNAL; | |
| 124 } else { | |
| 125 priority = ProcessPriority::CHROME_NORMAL; | |
| 126 } | |
| 127 if (tab.is_pinned) | |
| 128 priority |= ProcessPriority::CHROME_PINNED; | |
| 129 if (tab.is_media) | |
| 130 priority |= ProcessPriority::CHROME_MEDIA; | |
| 131 if (tab.has_form_entry) | |
| 132 priority |= ProcessPriority::CHROME_CANT_SAVE_STATE; | |
| 133 | |
| 134 return priority; | |
| 135 } | |
| 136 | |
| 137 bool IsArcMemoryManagementEnabled() { | 78 bool IsArcMemoryManagementEnabled() { |
| 138 return base::FeatureList::IsEnabled(features::kArcMemoryManagement); | 79 return base::FeatureList::IsEnabled(features::kArcMemoryManagement); |
| 139 } | 80 } |
| 140 | 81 |
| 141 } // namespace | 82 } // namespace |
| 142 | 83 |
| 143 std::ostream& operator<<( | 84 std::ostream& operator<<( |
| 144 std::ostream& out, const TabManagerDelegate::Candidate& candidate) { | 85 std::ostream& out, const TabManagerDelegate::Candidate& candidate) { |
| 145 if (candidate.is_arc_app) { | 86 if (candidate.app()) { |
| 146 out << "app " << candidate.app->pid() | 87 out << "app " << candidate.app()->pid() |
| 147 << " (" << candidate.app->process_name() << ")"; | 88 << " (" << candidate.app()->process_name() << ")" |
| 148 } else { | 89 << ", adj " << candidate.app()->adj() |
| 149 out << "tab " << candidate.tab->renderer_handle; | 90 << ", lastActivityTime " << candidate.app()->last_activity_time(); |
| 91 } else if (candidate.tab()) { | |
| 92 out << "tab " << candidate.tab()->renderer_handle; | |
| 150 } | 93 } |
| 151 out << " with priority " << candidate.priority; | 94 out << ", process_type " << candidate.process_type(); |
| 152 return out; | 95 return out; |
| 153 } | 96 } |
| 154 | 97 |
| 155 // Holds the info of a newly focused tab or app window. The focused process is | 98 // Holds the info of a newly focused tab or app window. The focused process is |
| 156 // set to highest priority (lowest OOM score), but not immediately. To avoid | 99 // set to highest priority (lowest OOM score), but not immediately. To avoid |
| 157 // redundant settings the OOM score adjusting only happens after a timeout. If | 100 // redundant settings the OOM score adjusting only happens after a timeout. If |
| 158 // the process loses focus before the timeout, the adjustment is canceled. | 101 // the process loses focus before the timeout, the adjustment is canceled. |
| 159 // | 102 // |
| 160 // This information might be set on UI thread and looked up on FILE thread. So a | 103 // This information might be set on UI thread and looked up on FILE thread. So a |
| 161 // lock is needed to avoid racing. | 104 // lock is needed to avoid racing. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB( | 220 int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB( |
| 278 base::ProcessHandle pid) { | 221 base::ProcessHandle pid) { |
| 279 std::unique_ptr<base::ProcessMetrics> process_metrics( | 222 std::unique_ptr<base::ProcessMetrics> process_metrics( |
| 280 base::ProcessMetrics::CreateProcessMetrics(pid)); | 223 base::ProcessMetrics::CreateProcessMetrics(pid)); |
| 281 base::WorkingSetKBytes mem_usage; | 224 base::WorkingSetKBytes mem_usage; |
| 282 process_metrics->GetWorkingSetKBytes(&mem_usage); | 225 process_metrics->GetWorkingSetKBytes(&mem_usage); |
| 283 return mem_usage.priv; | 226 return mem_usage.priv; |
| 284 } | 227 } |
| 285 | 228 |
| 286 class TabManagerDelegate::UmaReporter { | 229 class TabManagerDelegate::UmaReporter { |
| 287 public: | 230 public: |
| 288 UmaReporter() | 231 UmaReporter() |
| 289 : last_kill_time_(), total_kills_(0) {} | 232 : last_kill_time_(), total_kills_(0) {} |
| 290 ~UmaReporter() {} | 233 ~UmaReporter() {} |
| 291 void ReportKill(const int memory_freed); | 234 void ReportKill(const int memory_freed); |
| 292 | 235 |
| 293 private: | 236 private: |
| 294 base::Time last_kill_time_; | 237 base::Time last_kill_time_; |
| 295 int total_kills_; | 238 int total_kills_; |
| 296 }; | 239 }; |
| 297 | 240 |
| 298 void TabManagerDelegate::UmaReporter::ReportKill(const int memory_freed) { | 241 void TabManagerDelegate::UmaReporter::ReportKill(const int memory_freed) { |
| 299 base::Time now = base::Time::Now(); | 242 base::Time now = base::Time::Now(); |
| 300 const TimeDelta time_delta = | 243 const TimeDelta time_delta = |
| 301 last_kill_time_.is_null() ? | 244 last_kill_time_.is_null() ? |
| 302 TimeDelta::FromSeconds(arc::kMaxOomMemoryKillTimeDeltaSecs) : | 245 TimeDelta::FromSeconds(arc::kMaxOomMemoryKillTimeDeltaSecs) : |
| 303 (now - last_kill_time_); | 246 (now - last_kill_time_); |
| 304 UMA_HISTOGRAM_OOM_KILL_TIME_INTERVAL( | 247 UMA_HISTOGRAM_OOM_KILL_TIME_INTERVAL( |
| 305 "Arc.LowMemoryKiller.TimeDelta", time_delta); | 248 "Arc.LowMemoryKiller.TimeDelta", time_delta); |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 397 } | 340 } |
| 398 VLOG(2) << "Disable LowMemoryKiller"; | 341 VLOG(2) << "Disable LowMemoryKiller"; |
| 399 arc_process_instance_->DisableLowMemoryKiller(); | 342 arc_process_instance_->DisableLowMemoryKiller(); |
| 400 } | 343 } |
| 401 | 344 |
| 402 void TabManagerDelegate::OnProcessInstanceClosed() { | 345 void TabManagerDelegate::OnProcessInstanceClosed() { |
| 403 arc_process_instance_ = nullptr; | 346 arc_process_instance_ = nullptr; |
| 404 arc_process_instance_version_ = 0; | 347 arc_process_instance_version_ = 0; |
| 405 } | 348 } |
| 406 | 349 |
| 350 // TODO(cylee): Remove this function if Android process OOM score settings | |
| 351 // is moved back to Android. | |
| 352 // For example, negotiate non-overlapping OOM score ranges so Chrome and Android | |
| 353 // can set OOM score for processes in their own world. | |
| 407 void TabManagerDelegate::OnWindowActivated( | 354 void TabManagerDelegate::OnWindowActivated( |
| 408 aura::client::ActivationChangeObserver::ActivationReason reason, | 355 aura::client::ActivationChangeObserver::ActivationReason reason, |
| 409 aura::Window* gained_active, | 356 aura::Window* gained_active, |
| 410 aura::Window* lost_active) { | 357 aura::Window* lost_active) { |
| 411 if (IsArcWindow(gained_active)) { | 358 if (IsArcWindow(gained_active)) { |
| 412 // Currently there is no way to know which app is displayed in the ARC | 359 // Currently there is no way to know which app is displayed in the ARC |
| 413 // window, so schedule an early adjustment for all processes to reflect | 360 // window, so schedule an early adjustment for all processes to reflect |
| 414 // the change. | 361 // the change. |
| 415 // Put a dummy FocusedProcess with nspid = kInvalidArcAppNspid for now to | 362 // Put a dummy FocusedProcess with nspid = kInvalidArcAppNspid for now to |
| 416 // indicate the focused process is an arc app. | 363 // indicate the focused process is an arc app. |
| (...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 590 base::Bind(&TabManagerDelegate::AdjustOomPrioritiesImpl, | 537 base::Bind(&TabManagerDelegate::AdjustOomPrioritiesImpl, |
| 591 weak_ptr_factory_.GetWeakPtr(), tab_list))) { | 538 weak_ptr_factory_.GetWeakPtr(), tab_list))) { |
| 592 return; | 539 return; |
| 593 } | 540 } |
| 594 } | 541 } |
| 595 // Pass in a dummy list if unable to get ARC processes. | 542 // Pass in a dummy list if unable to get ARC processes. |
| 596 AdjustOomPrioritiesImpl(tab_list, std::vector<arc::ArcProcess>()); | 543 AdjustOomPrioritiesImpl(tab_list, std::vector<arc::ArcProcess>()); |
| 597 } | 544 } |
| 598 | 545 |
| 599 // Excludes persistent ARC apps, but still preserves active chrome tabs and | 546 // Excludes persistent ARC apps, but still preserves active chrome tabs and |
| 600 // top ARC apps. The latter ones should not be killed by TabManager since | 547 // focused ARC apps. The latter ones should not be killed by TabManager here, |
| 601 // we still want to adjust their oom_score_adj. | 548 // but we want to adjust their oom_score_adj. |
| 602 // static | 549 // static |
| 603 std::vector<TabManagerDelegate::Candidate> | 550 std::vector<TabManagerDelegate::Candidate> |
| 604 TabManagerDelegate::GetSortedCandidates( | 551 TabManagerDelegate::GetSortedCandidates( |
| 605 const TabStatsList& tab_list, | 552 const TabStatsList& tab_list, |
| 606 const std::vector<arc::ArcProcess>& arc_processes) { | 553 const std::vector<arc::ArcProcess>& arc_processes) { |
| 607 | 554 |
| 555 static const char kAppLauncherProcessName[] = "org.chromium.arc.applauncher"; | |
| 556 | |
| 608 std::vector<Candidate> candidates; | 557 std::vector<Candidate> candidates; |
| 609 candidates.reserve(tab_list.size() + arc_processes.size()); | 558 candidates.reserve(tab_list.size() + arc_processes.size()); |
| 610 | 559 |
| 611 for (const auto& tab : tab_list) { | 560 for (const auto& tab : tab_list) { |
| 612 candidates.push_back(Candidate(&tab, TabStatsToPriority(tab))); | 561 candidates.push_back(Candidate(&tab)); |
| 613 } | 562 } |
| 614 | 563 |
| 615 for (const auto& app : arc_processes) { | 564 for (const auto& app : arc_processes) { |
| 616 Candidate candidate(&app, AppStateToPriority(app.process_state())); | 565 // Persistent an system android processes has negative adj value. |
|
Georges Khalil
2016/06/27 20:15:04
nits:
- an -> and
- has -> have
cylee1
2016/07/14 19:15:24
Done.
| |
| 617 // Skip persistent android processes since we should never kill them. | 566 // Skip them since they should never be killed here. Also don't ajust |
| 618 // Also don't ajust OOM score so their score remains min oom_score_adj. | 567 // OOM score so their score remains min oom_score_adj. |
| 619 if (candidate.priority >= ProcessPriority::ANDROID_PERSISTENT) | 568 // |
| 569 // AppLauncher is treated specially in ARC++. For example it is taken | |
| 570 // as the dummy foreground app from Android's point of view when the focused | |
| 571 // window is not an Android app. We prefer never kill it. | |
| 572 if (app.adj() < 0 || app.process_name() == kAppLauncherProcessName) | |
| 620 continue; | 573 continue; |
| 621 candidates.push_back(candidate); | 574 candidates.push_back(Candidate(&app)); |
| 622 } | 575 } |
| 623 | 576 |
| 624 // Sort candidates according to priority. | 577 // Sort candidates according to priority. |
| 625 // TODO(cylee): Missing LRU property. Fix it when apps has the information. | |
| 626 std::sort(candidates.begin(), candidates.end()); | 578 std::sort(candidates.begin(), candidates.end()); |
| 627 | 579 |
| 628 return candidates; | 580 return candidates; |
| 629 } | 581 } |
| 630 | 582 |
| 631 bool TabManagerDelegate::KillArcProcess(const int nspid) { | 583 bool TabManagerDelegate::KillArcProcess(const int nspid) { |
| 632 if (!arc_process_instance_) | 584 if (!arc_process_instance_) |
| 633 return false; | 585 return false; |
| 634 arc_process_instance_->KillProcess(nspid, "LowMemoryKill"); | 586 arc_process_instance_->KillProcess(nspid, "LowMemoryKill"); |
| 635 return true; | 587 return true; |
| 636 } | 588 } |
| 637 | 589 |
| 638 bool TabManagerDelegate::KillTab(int64_t tab_id) { | 590 bool TabManagerDelegate::KillTab(int64_t tab_id) { |
| 639 // Check |tab_manager_| is alive before taking tabs into consideration. | 591 // Check |tab_manager_| is alive before taking tabs into consideration. |
| 640 return tab_manager_ && | 592 return tab_manager_ && |
| 641 tab_manager_->CanDiscardTab(tab_id) && | 593 tab_manager_->CanDiscardTab(tab_id) && |
| 642 tab_manager_->DiscardTabById(tab_id); | 594 tab_manager_->DiscardTabById(tab_id); |
| 643 } | 595 } |
| 644 | 596 |
| 645 void TabManagerDelegate::LowMemoryKillImpl( | 597 void TabManagerDelegate::LowMemoryKillImpl( |
| 646 const TabStatsList& tab_list, | 598 const TabStatsList& tab_list, |
| 647 const std::vector<arc::ArcProcess>& arc_processes) { | 599 const std::vector<arc::ArcProcess>& arc_processes) { |
| 648 | 600 |
| 649 VLOG(2) << "LowMemoryKilleImpl"; | 601 VLOG(2) << "LowMemoryKilleImpl"; |
| 650 std::vector<TabManagerDelegate::Candidate> candidates = | 602 const std::vector<TabManagerDelegate::Candidate> candidates = |
| 651 GetSortedCandidates(tab_list, arc_processes); | 603 GetSortedCandidates(tab_list, arc_processes); |
| 652 | 604 |
| 653 int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB(); | 605 int target_memory_to_free_kb = mem_stat_->TargetMemoryToFreeKB(); |
| 654 for (const auto& entry : candidates) { | 606 // Kill processes until the estimated amount of freed memory is sufficient to |
| 607 // bring the system memory back to a normal level. | |
| 608 // The list is sorted by importance descendingly, so we go through the list | |
| 609 // backwards. | |
| 610 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { | |
| 655 VLOG(3) << "Target memory to free: " << target_memory_to_free_kb << " KB"; | 611 VLOG(3) << "Target memory to free: " << target_memory_to_free_kb << " KB"; |
| 656 // Never kill selected tab or Android foreground app, regardless whether | 612 // Never kill selected tab or Android foreground app, regardless whether |
| 657 // they're in the active window. Since the user experience would be bad. | 613 // they're in the active window. Since the user experience would be bad. |
| 658 if ((!entry.is_arc_app && | 614 ProcessType process_type = it->process_type(); |
| 659 entry.priority >= ProcessPriority::CHROME_SELECTED) || | 615 if (process_type == ProcessType::VISIBLE_APP || |
| 660 (entry.is_arc_app && | 616 process_type == ProcessType::FOCUSED_APP || |
| 661 entry.priority >= ProcessPriority::ANDROID_TOP_INACTIVE)) { | 617 process_type == ProcessType::FOCUSED_TAB) { |
| 662 VLOG(2) << "Skipped killing " << entry; | 618 VLOG(2) << "Skipped killing " << *it; |
| 663 continue; | 619 continue; |
| 664 } | 620 } |
| 665 if (entry.is_arc_app) { | 621 if (it->app()) { |
| 666 int estimated_memory_freed_kb = | 622 int estimated_memory_freed_kb = |
| 667 mem_stat_->EstimatedMemoryFreedKB(entry.app->pid()); | 623 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); |
| 668 if (KillArcProcess(entry.app->nspid())) { | 624 if (KillArcProcess(it->app()->nspid())) { |
| 669 target_memory_to_free_kb -= estimated_memory_freed_kb; | 625 target_memory_to_free_kb -= estimated_memory_freed_kb; |
| 670 uma_->ReportKill(estimated_memory_freed_kb); | 626 uma_->ReportKill(estimated_memory_freed_kb); |
| 671 VLOG(2) << "Killed " << entry; | 627 VLOG(2) << "Killed " << *it; |
| 672 } | 628 } |
| 673 } else { | 629 } else { |
| 674 int64_t tab_id = entry.tab->tab_contents_id; | 630 int64_t tab_id = it->tab()->tab_contents_id; |
| 675 int estimated_memory_freed_kb = | 631 int estimated_memory_freed_kb = |
| 676 mem_stat_->EstimatedMemoryFreedKB(entry.tab->renderer_handle); | 632 mem_stat_->EstimatedMemoryFreedKB(it->tab()->renderer_handle); |
| 677 if (KillTab(tab_id)) { | 633 if (KillTab(tab_id)) { |
| 678 target_memory_to_free_kb -= estimated_memory_freed_kb; | 634 target_memory_to_free_kb -= estimated_memory_freed_kb; |
| 679 uma_->ReportKill(estimated_memory_freed_kb); | 635 uma_->ReportKill(estimated_memory_freed_kb); |
| 680 VLOG(2) << "Killed " << entry; | 636 VLOG(2) << "Killed " << *it; |
| 681 } | 637 } |
| 682 } | 638 } |
| 683 if (target_memory_to_free_kb < 0) | 639 if (target_memory_to_free_kb < 0) |
| 684 break; | 640 break; |
| 685 } | 641 } |
| 686 } | 642 } |
| 687 | 643 |
| 688 void TabManagerDelegate::AdjustOomPrioritiesImpl( | 644 void TabManagerDelegate::AdjustOomPrioritiesImpl( |
| 689 const TabStatsList& tab_list, | 645 const TabStatsList& tab_list, |
| 690 const std::vector<arc::ArcProcess>& arc_processes) { | 646 const std::vector<arc::ArcProcess>& arc_processes) { |
| 691 // Least important first. | 647 // Least important first. |
| 692 auto candidates = GetSortedCandidates(tab_list, arc_processes); | 648 const auto candidates = GetSortedCandidates(tab_list, arc_processes); |
| 693 | 649 |
| 694 // Now we assign priorities based on the sorted list. We're assigning | 650 // Now we assign priorities based on the sorted list. We're assigning |
| 695 // priorities in the range of kLowestRendererOomScore to | 651 // priorities in the range of kLowestRendererOomScore to |
| 696 // kHighestRendererOomScore (defined in chrome_constants.h). oom_score_adj | 652 // kHighestRendererOomScore (defined in chrome_constants.h). oom_score_adj |
| 697 // takes values from -1000 to 1000. Negative values are reserved for system | 653 // takes values from -1000 to 1000. Negative values are reserved for system |
| 698 // processes, and we want to give some room below the range we're using to | 654 // processes, and we want to give some room below the range we're using to |
| 699 // allow for things that want to be above the renderers in priority, so the | 655 // allow for things that want to be above the renderers in priority, so the |
| 700 // defined range gives us some variation in priority without taking up the | 656 // defined range gives us some variation in priority without taking up the |
| 701 // whole range. In the end, however, it's a pretty arbitrary range to use. | 657 // whole range. In the end, however, it's a pretty arbitrary range to use. |
| 702 // Higher values are more likely to be killed by the OOM killer. | 658 // Higher values are more likely to be killed by the OOM killer. |
| 703 | 659 |
| 704 // Break the processes into 2 parts. This is to help lower the chance of | 660 // Break the processes into 2 parts. This is to help lower the chance of |
| 705 // altering OOM score for many processes on any small change. | 661 // altering OOM score for many processes on any small change. |
| 706 int range_middle = | 662 int range_middle = |
| 707 (chrome::kLowestRendererOomScore + chrome::kHighestRendererOomScore) / 2; | 663 (chrome::kLowestRendererOomScore + chrome::kHighestRendererOomScore) / 2; |
| 708 | 664 |
| 709 // Find some pivot point. For now processes with priority >= CHROME_INTERNAL | 665 // Find some pivot point. For now processes with priority >= CHROME_INTERNAL |
| 710 // are prone to be affected by LRU change. Taking them as "high priority" | 666 // are prone to be affected by LRU change. Taking them as "high priority" |
| 711 // processes. | 667 // processes. |
| 712 auto lower_priority_part = candidates.rend(); | 668 auto lower_priority_part = candidates.end(); |
| 713 // Iterate in reverse order since the list is sorted by least importance. | 669 for (auto it = candidates.begin(); it != candidates.end(); ++it) { |
| 714 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { | 670 if (it->process_type() >= ProcessType::BACKGROUND_APP) { |
| 715 if (it->priority < ProcessPriority::CHROME_INTERNAL) { | |
| 716 lower_priority_part = it; | 671 lower_priority_part = it; |
| 717 break; | 672 break; |
| 718 } | 673 } |
| 719 } | 674 } |
| 720 | 675 |
| 721 ProcessScoreMap new_map; | 676 ProcessScoreMap new_map; |
| 722 | 677 |
| 723 // Higher priority part. | 678 // Higher priority part. |
| 724 DistributeOomScoreInRange(candidates.rbegin(), lower_priority_part, | 679 DistributeOomScoreInRange(candidates.begin(), lower_priority_part, |
| 725 chrome::kLowestRendererOomScore, range_middle, | 680 chrome::kLowestRendererOomScore, range_middle, |
| 726 &new_map); | 681 &new_map); |
| 727 // Lower priority part. | 682 // Lower priority part. |
| 728 DistributeOomScoreInRange(lower_priority_part, candidates.rend(), | 683 DistributeOomScoreInRange(lower_priority_part, candidates.end(), |
| 729 range_middle, chrome::kHighestRendererOomScore, | 684 range_middle, chrome::kHighestRendererOomScore, |
| 730 &new_map); | 685 &new_map); |
| 731 base::AutoLock oom_score_autolock(oom_score_lock_); | 686 base::AutoLock oom_score_autolock(oom_score_lock_); |
| 732 oom_score_map_.swap(new_map); | 687 oom_score_map_.swap(new_map); |
| 733 } | 688 } |
| 734 | 689 |
| 735 void TabManagerDelegate::SetOomScoreAdjForApp(int nspid, int score) { | 690 void TabManagerDelegate::SetOomScoreAdjForApp(int nspid, int score) { |
| 736 if (!arc_process_instance_) | 691 if (!arc_process_instance_) |
| 737 return; | 692 return; |
| 738 if (arc_process_instance_version_ < 2) { | 693 if (arc_process_instance_version_ < 2) { |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 754 void TabManagerDelegate::SetOomScoreAdjForTabsOnFileThread( | 709 void TabManagerDelegate::SetOomScoreAdjForTabsOnFileThread( |
| 755 const std::vector<std::pair<base::ProcessHandle, int>>& entries) { | 710 const std::vector<std::pair<base::ProcessHandle, int>>& entries) { |
| 756 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 711 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
| 757 for (const auto& entry : entries) { | 712 for (const auto& entry : entries) { |
| 758 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore(entry.first, | 713 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore(entry.first, |
| 759 entry.second); | 714 entry.second); |
| 760 } | 715 } |
| 761 } | 716 } |
| 762 | 717 |
| 763 void TabManagerDelegate::DistributeOomScoreInRange( | 718 void TabManagerDelegate::DistributeOomScoreInRange( |
| 764 std::vector<TabManagerDelegate::Candidate>::reverse_iterator rbegin, | 719 std::vector<TabManagerDelegate::Candidate>::const_iterator begin, |
| 765 std::vector<TabManagerDelegate::Candidate>::reverse_iterator rend, | 720 std::vector<TabManagerDelegate::Candidate>::const_iterator end, |
| 766 int range_begin, | 721 int range_begin, |
| 767 int range_end, | 722 int range_end, |
| 768 ProcessScoreMap* new_map) { | 723 ProcessScoreMap* new_map) { |
| 769 // OOM score setting for tabs involves file system operation so should be | 724 // OOM score setting for tabs involves file system operation so should be |
| 770 // done on file thread. | 725 // done on file thread. |
| 771 std::vector<std::pair<base::ProcessHandle, int>> oom_score_for_tabs; | 726 std::vector<std::pair<base::ProcessHandle, int>> oom_score_for_tabs; |
| 772 | 727 |
| 773 // Though there might be duplicate process handles, it doesn't matter to | 728 // Though there might be duplicate process handles, it doesn't matter to |
| 774 // overestimate the number of processes here since the we don't need to | 729 // overestimate the number of processes here since the we don't need to |
| 775 // use up the full range. | 730 // use up the full range. |
| 776 int num = (rend - rbegin); | 731 int num = (end - begin); |
| 777 const float priority_increment = | 732 const float priority_increment = |
| 778 static_cast<float>(range_end - range_begin) / num; | 733 static_cast<float>(range_end - range_begin) / num; |
| 779 | 734 |
| 780 float priority = range_begin; | 735 float priority = range_begin; |
| 781 for (auto cur = rbegin; cur != rend; ++cur) { | 736 for (auto cur = begin; cur != end; ++cur) { |
| 782 int score = static_cast<int>(priority + 0.5f); | 737 int score = static_cast<int>(priority + 0.5f); |
| 783 if (cur->is_arc_app) { | 738 if (cur->app()) { |
| 784 // Use pid as map keys so it's globally unique. | 739 // Use pid as map keys so it's globally unique. |
| 785 (*new_map)[cur->app->pid()] = score; | 740 (*new_map)[cur->app()->pid()] = score; |
| 786 int cur_app_pid_score = 0; | 741 int cur_app_pid_score = 0; |
| 787 { | 742 { |
| 788 base::AutoLock oom_score_autolock(oom_score_lock_); | 743 base::AutoLock oom_score_autolock(oom_score_lock_); |
| 789 cur_app_pid_score = oom_score_map_[cur->app->pid()]; | 744 cur_app_pid_score = oom_score_map_[cur->app()->pid()]; |
| 790 } | 745 } |
| 791 if (cur_app_pid_score != score) { | 746 if (cur_app_pid_score != score) { |
| 792 VLOG(3) << "Set OOM score " << score << " for " << *cur; | 747 VLOG(3) << "Set OOM score " << score << " for " << *cur; |
| 793 SetOomScoreAdjForApp(cur->app->nspid(), score); | 748 SetOomScoreAdjForApp(cur->app()->nspid(), score); |
| 794 } | 749 } |
| 795 } else { | 750 } else { |
| 796 base::ProcessHandle process_handle = cur->tab->renderer_handle; | 751 base::ProcessHandle process_handle = cur->tab()->renderer_handle; |
| 797 // 1. tab_list contains entries for already-discarded tabs. If the PID | 752 // 1. tab_list contains entries for already-discarded tabs. If the PID |
| 798 // (renderer_handle) is zero, we don't need to adjust the oom_score. | 753 // (renderer_handle) is zero, we don't need to adjust the oom_score. |
| 799 // 2. Only add unseen process handle so if there's multiple tab maps to | 754 // 2. Only add unseen process handle so if there's multiple tab maps to |
| 800 // the same process, the process is set to an OOM score based on its "most | 755 // the same process, the process is set to an OOM score based on its "most |
| 801 // important" tab. | 756 // important" tab. |
| 802 if (process_handle != 0 && | 757 if (process_handle != 0 && |
| 803 new_map->find(process_handle) == new_map->end()) { | 758 new_map->find(process_handle) == new_map->end()) { |
| 804 (*new_map)[process_handle] = score; | 759 (*new_map)[process_handle] = score; |
| 805 int process_handle_score = 0; | 760 int process_handle_score = 0; |
| 806 { | 761 { |
| 807 base::AutoLock oom_score_autolock(oom_score_lock_); | 762 base::AutoLock oom_score_autolock(oom_score_lock_); |
| 808 process_handle_score = oom_score_map_[process_handle]; | 763 process_handle_score = oom_score_map_[process_handle]; |
| 809 } | 764 } |
| 810 if (process_handle_score != score) { | 765 if (process_handle_score != score) { |
| 811 oom_score_for_tabs.push_back(std::make_pair(process_handle, score)); | 766 oom_score_for_tabs.push_back(std::make_pair(process_handle, score)); |
| 812 VLOG(3) << "Set OOM score " << score << " for " << *cur; | 767 VLOG(3) << "Set OOM score " << score << " for " << *cur; |
| 813 } | 768 } |
| 814 } else { | 769 } else { |
| 815 continue; // Skip priority increment. | 770 continue; // Skip priority increment. |
| 816 } | 771 } |
| 817 } | 772 } |
| 818 priority += priority_increment; | 773 priority += priority_increment; |
| 819 } | 774 } |
| 820 | 775 |
| 821 if (oom_score_for_tabs.size()) | 776 if (oom_score_for_tabs.size()) |
| 822 SetOomScoreAdjForTabs(oom_score_for_tabs); | 777 SetOomScoreAdjForTabs(oom_score_for_tabs); |
| 823 } | 778 } |
| 824 | 779 |
| 825 } // namespace memory | 780 } // namespace memory |
| OLD | NEW |