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 <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <map> | 10 #include <map> |
(...skipping 18 matching lines...) Expand all Loading... | |
29 #include "chrome/browser/memory/memory_kills_monitor.h" | 29 #include "chrome/browser/memory/memory_kills_monitor.h" |
30 #include "chrome/browser/memory/tab_stats.h" | 30 #include "chrome/browser/memory/tab_stats.h" |
31 #include "chrome/browser/ui/browser.h" | 31 #include "chrome/browser/ui/browser.h" |
32 #include "chrome/browser/ui/browser_list.h" | 32 #include "chrome/browser/ui/browser_list.h" |
33 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 33 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
34 #include "chrome/common/chrome_constants.h" | 34 #include "chrome/common/chrome_constants.h" |
35 #include "chrome/common/chrome_features.h" | 35 #include "chrome/common/chrome_features.h" |
36 #include "chromeos/dbus/dbus_thread_manager.h" | 36 #include "chromeos/dbus/dbus_thread_manager.h" |
37 #include "components/arc/arc_bridge_service.h" | 37 #include "components/arc/arc_bridge_service.h" |
38 #include "components/arc/arc_service_manager.h" | 38 #include "components/arc/arc_service_manager.h" |
39 #include "components/arc/common/process.mojom.h" | |
40 #include "components/device_event_log/device_event_log.h" | 39 #include "components/device_event_log/device_event_log.h" |
41 #include "components/exo/shell_surface.h" | 40 #include "components/exo/shell_surface.h" |
42 #include "content/public/browser/browser_thread.h" | 41 #include "content/public/browser/browser_thread.h" |
43 #include "content/public/browser/notification_service.h" | 42 #include "content/public/browser/notification_service.h" |
44 #include "content/public/browser/notification_types.h" | 43 #include "content/public/browser/notification_types.h" |
45 #include "content/public/browser/render_process_host.h" | 44 #include "content/public/browser/render_process_host.h" |
46 #include "content/public/browser/render_widget_host.h" | 45 #include "content/public/browser/render_widget_host.h" |
47 #include "content/public/browser/zygote_host_linux.h" | 46 #include "content/public/browser/zygote_host_linux.h" |
48 #include "ui/aura/window.h" | 47 #include "ui/aura/window.h" |
49 #include "ui/wm/public/activation_client.h" | 48 #include "ui/wm/public/activation_client.h" |
(...skipping 29 matching lines...) Expand all Loading... | |
79 return base::StartsWith(application_id, kArcProcessNamePrefix, | 78 return base::StartsWith(application_id, kArcProcessNamePrefix, |
80 base::CompareCase::SENSITIVE); | 79 base::CompareCase::SENSITIVE); |
81 } | 80 } |
82 | 81 |
83 bool IsArcMemoryManagementEnabled() { | 82 bool IsArcMemoryManagementEnabled() { |
84 return base::FeatureList::IsEnabled(features::kArcMemoryManagement); | 83 return base::FeatureList::IsEnabled(features::kArcMemoryManagement); |
85 } | 84 } |
86 | 85 |
87 void OnSetOomScoreAdj(bool success, const std::string& output) { | 86 void OnSetOomScoreAdj(bool success, const std::string& output) { |
88 VLOG(2) << "OnSetOomScoreAdj " << success << " " << output; | 87 VLOG(2) << "OnSetOomScoreAdj " << success << " " << output; |
89 if (!success || output != "") | 88 if (!success) |
90 LOG(WARNING) << "Set OOM score error: " << output; | 89 LOG(ERROR) << "Set OOM score error: " << output; |
90 else if (!output.empty()) | |
91 LOG(WARNING) << "Set OOM score: " << output; | |
91 } | 92 } |
92 | 93 |
93 } // namespace | 94 } // namespace |
94 | 95 |
96 // static | |
97 const int TabManagerDelegate::kLowestOomScore = -1000; | |
98 | |
95 std::ostream& operator<<(std::ostream& os, const ProcessType& type) { | 99 std::ostream& operator<<(std::ostream& os, const ProcessType& type) { |
96 switch (type) { | 100 switch (type) { |
97 case ProcessType::FOCUSED_TAB: | 101 case ProcessType::FOCUSED_TAB: |
98 return os << "FOCUSED_TAB"; | 102 return os << "FOCUSED_TAB"; |
99 case ProcessType::FOCUSED_APP: | 103 case ProcessType::FOCUSED_APP: |
100 return os << "FOCUSED_APP"; | 104 return os << "FOCUSED_APP"; |
101 case ProcessType::VISIBLE_APP: | 105 case ProcessType::VISIBLE_APP: |
102 return os << "VISIBLE_APP"; | 106 return os << "VISIBLE_APP"; |
103 case ProcessType::BACKGROUND_TAB: | 107 case ProcessType::BACKGROUND_TAB: |
104 return os << "BACKGROUND_TAB"; | 108 return os << "BACKGROUND_TAB"; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
148 // apps. | 152 // apps. |
149 NOTREACHED() << "Undefined comparison between apps and tabs: process_type=" | 153 NOTREACHED() << "Undefined comparison between apps and tabs: process_type=" |
150 << process_type(); | 154 << process_type(); |
151 return app(); | 155 return app(); |
152 } | 156 } |
153 | 157 |
154 ProcessType TabManagerDelegate::Candidate::GetProcessTypeInternal() const { | 158 ProcessType TabManagerDelegate::Candidate::GetProcessTypeInternal() const { |
155 if (app()) { | 159 if (app()) { |
156 if (app()->is_focused()) | 160 if (app()->is_focused()) |
157 return ProcessType::FOCUSED_APP; | 161 return ProcessType::FOCUSED_APP; |
158 if (app()->process_state() <= | 162 if (app()->IsUserVisible()) |
159 arc::mojom::ProcessState::IMPORTANT_FOREGROUND) { | |
160 return ProcessType::VISIBLE_APP; | 163 return ProcessType::VISIBLE_APP; |
cylee1
2017/05/10 16:31:55
Let's rename it, it's no longer "visible app" but
Yusuke Sato
2017/05/10 18:29:43
Done.
| |
161 } | |
162 return ProcessType::BACKGROUND_APP; | 164 return ProcessType::BACKGROUND_APP; |
163 } | 165 } |
164 if (tab()) { | 166 if (tab()) { |
165 if (tab()->is_selected) | 167 if (tab()->is_selected) |
166 return ProcessType::FOCUSED_TAB; | 168 return ProcessType::FOCUSED_TAB; |
167 return ProcessType::BACKGROUND_TAB; | 169 return ProcessType::BACKGROUND_TAB; |
168 } | 170 } |
169 NOTREACHED() << "Unexpected process type"; | 171 NOTREACHED() << "Unexpected process type"; |
170 return ProcessType::UNKNOWN_TYPE; | 172 return ProcessType::UNKNOWN_TYPE; |
171 } | 173 } |
(...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
524 TabManagerDelegate::GetSortedCandidates( | 526 TabManagerDelegate::GetSortedCandidates( |
525 const TabStatsList& tab_list, | 527 const TabStatsList& tab_list, |
526 const std::vector<arc::ArcProcess>& arc_processes) { | 528 const std::vector<arc::ArcProcess>& arc_processes) { |
527 std::vector<Candidate> candidates; | 529 std::vector<Candidate> candidates; |
528 candidates.reserve(tab_list.size() + arc_processes.size()); | 530 candidates.reserve(tab_list.size() + arc_processes.size()); |
529 | 531 |
530 for (const auto& tab : tab_list) { | 532 for (const auto& tab : tab_list) { |
531 candidates.emplace_back(&tab); | 533 candidates.emplace_back(&tab); |
532 } | 534 } |
533 | 535 |
534 // A special process on Android side which serves as a dummy "focused" app | |
535 // when the focused window is a Chrome side window (i.e., all Android | |
536 // processes are running in the background). We don't want to kill it anyway. | |
537 static constexpr char kArcInBackgroundDummyprocess[] = | |
538 "org.chromium.arc.home"; | |
539 | |
540 for (const auto& app : arc_processes) { | 536 for (const auto& app : arc_processes) { |
541 // Skip persistent android processes since they should never be killed here. | |
542 // Neither do we set their OOM scores so their score remains minimum. | |
543 if (app.process_state() <= arc::mojom::ProcessState::PERSISTENT_UI || | |
544 app.process_name() == kArcInBackgroundDummyprocess) { | |
545 continue; | |
546 } | |
547 candidates.emplace_back(&app); | 537 candidates.emplace_back(&app); |
548 } | 538 } |
549 | 539 |
550 // Sort candidates according to priority. | 540 // Sort candidates according to priority. |
551 std::sort(candidates.begin(), candidates.end()); | 541 std::sort(candidates.begin(), candidates.end()); |
552 | 542 |
553 return candidates; | 543 return candidates; |
554 } | 544 } |
555 | 545 |
556 bool TabManagerDelegate::IsRecentlyKilledArcProcess( | 546 bool TabManagerDelegate::IsRecentlyKilledArcProcess( |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 | 592 |
603 // Kill processes until the estimated amount of freed memory is sufficient to | 593 // Kill processes until the estimated amount of freed memory is sufficient to |
604 // bring the system memory back to a normal level. | 594 // bring the system memory back to a normal level. |
605 // The list is sorted by descending importance, so we go through the list | 595 // The list is sorted by descending importance, so we go through the list |
606 // backwards. | 596 // backwards. |
607 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { | 597 for (auto it = candidates.rbegin(); it != candidates.rend(); ++it) { |
608 MEMORY_LOG(ERROR) << "Target memory to free: " << target_memory_to_free_kb | 598 MEMORY_LOG(ERROR) << "Target memory to free: " << target_memory_to_free_kb |
609 << " KB"; | 599 << " KB"; |
610 if (target_memory_to_free_kb <= 0) | 600 if (target_memory_to_free_kb <= 0) |
611 break; | 601 break; |
612 // Never kill selected tab or Android foreground app, regardless whether | 602 // Never kill selected tab, foreground app, and visible apps regardless of |
613 // they're in the active window. Since the user experience would be bad. | 603 // whether they're in the active window. Since the user experience would be |
604 // bad. | |
614 ProcessType process_type = it->process_type(); | 605 ProcessType process_type = it->process_type(); |
615 if (process_type == ProcessType::VISIBLE_APP || | 606 if (process_type <= ProcessType::VISIBLE_APP) { |
616 process_type == ProcessType::FOCUSED_APP || | |
617 process_type == ProcessType::FOCUSED_TAB) { | |
618 MEMORY_LOG(ERROR) << "Skipped killing " << *it; | 607 MEMORY_LOG(ERROR) << "Skipped killing " << *it; |
619 continue; | 608 continue; |
620 } | 609 } |
621 if (it->app()) { | 610 if (it->app()) { |
622 if (IsRecentlyKilledArcProcess(it->app()->process_name(), now)) { | 611 if (IsRecentlyKilledArcProcess(it->app()->process_name(), now)) { |
623 MEMORY_LOG(ERROR) << "Avoided killing " << *it << " too often"; | 612 MEMORY_LOG(ERROR) << "Avoided killing " << *it << " too often"; |
624 continue; | 613 continue; |
625 } | 614 } |
626 int estimated_memory_freed_kb = | 615 int estimated_memory_freed_kb = |
627 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); | 616 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); |
(...skipping 25 matching lines...) Expand all Loading... | |
653 } | 642 } |
654 if (target_memory_to_free_kb > 0) { | 643 if (target_memory_to_free_kb > 0) { |
655 MEMORY_LOG(ERROR) | 644 MEMORY_LOG(ERROR) |
656 << "Unable to kill enough candidates to meet target_memory_to_free_kb "; | 645 << "Unable to kill enough candidates to meet target_memory_to_free_kb "; |
657 } | 646 } |
658 } | 647 } |
659 | 648 |
660 void TabManagerDelegate::AdjustOomPrioritiesImpl( | 649 void TabManagerDelegate::AdjustOomPrioritiesImpl( |
661 const TabStatsList& tab_list, | 650 const TabStatsList& tab_list, |
662 const std::vector<arc::ArcProcess>& arc_processes) { | 651 const std::vector<arc::ArcProcess>& arc_processes) { |
652 std::vector<TabManagerDelegate::Candidate> candidates; | |
653 std::vector<TabManagerDelegate::Candidate> apps_non_killable; | |
654 | |
663 // Least important first. | 655 // Least important first. |
664 const auto candidates = GetSortedCandidates(tab_list, arc_processes); | 656 auto all_candidates = GetSortedCandidates(tab_list, arc_processes); |
657 for (auto& candidate : all_candidates) { | |
cylee1
2017/05/10 16:31:55
const auto ?
Yusuke Sato
2017/05/10 18:29:43
This is non-const for the std::move calls.
cylee1
2017/05/11 08:59:53
Acknowledged.
| |
658 if (!candidate.app() || candidate.app()->IsKernelKillable()) { | |
659 // Add tabs and killable apps to |candidates|. | |
660 candidates.emplace_back(std::move(candidate)); | |
661 } else { | |
662 // Add non-killable apps to |apps_non_killable|. | |
663 apps_non_killable.emplace_back(std::move(candidate)); | |
664 } | |
665 } | |
665 | 666 |
666 // Now we assign priorities based on the sorted list. We're assigning | 667 // Now we assign priorities based on the sorted list. We're assigning |
667 // priorities in the range of kLowestRendererOomScore to | 668 // priorities in the range of kLowestRendererOomScore to |
668 // kHighestRendererOomScore (defined in chrome_constants.h). oom_score_adj | 669 // kHighestRendererOomScore (defined in chrome_constants.h). oom_score_adj |
669 // takes values from -1000 to 1000. Negative values are reserved for system | 670 // takes values from -1000 to 1000. Negative values are reserved for system |
670 // processes, and we want to give some room below the range we're using to | 671 // processes, and we want to give some room below the range we're using to |
671 // allow for things that want to be above the renderers in priority, so the | 672 // allow for things that want to be above the renderers in priority, so the |
672 // defined range gives us some variation in priority without taking up the | 673 // defined range gives us some variation in priority without taking up the |
673 // whole range. In the end, however, it's a pretty arbitrary range to use. | 674 // whole range. In the end, however, it's a pretty arbitrary range to use. |
674 // Higher values are more likely to be killed by the OOM killer. | 675 // Higher values are more likely to be killed by the OOM killer. |
675 | 676 |
676 // Break the processes into 2 parts. This is to help lower the chance of | 677 // Break the processes into 2 parts. This is to help lower the chance of |
677 // altering OOM score for many processes on any small change. | 678 // altering OOM score for many processes on any small change. |
678 int range_middle = | 679 int range_middle = |
679 (chrome::kLowestRendererOomScore + chrome::kHighestRendererOomScore) / 2; | 680 (chrome::kLowestRendererOomScore + chrome::kHighestRendererOomScore) / 2; |
680 | 681 |
681 // Find some pivot point. For now processes with priority >= CHROME_INTERNAL | 682 // Find some pivot point. For now processes with priority >= CHROME_INTERNAL |
682 // are prone to be affected by LRU change. Taking them as "high priority" | 683 // are prone to be affected by LRU change. Taking them as "high priority" |
683 // processes. | 684 // processes. |
684 auto lower_priority_part = candidates.end(); | 685 auto lower_priority_part = candidates.end(); |
685 for (auto it = candidates.begin(); it != candidates.end(); ++it) { | 686 for (auto it = candidates.begin(); it != candidates.end(); ++it) { |
686 if (it->process_type() >= ProcessType::BACKGROUND_APP) { | 687 if (it->process_type() >= ProcessType::BACKGROUND_APP) { |
687 lower_priority_part = it; | 688 lower_priority_part = it; |
688 break; | 689 break; |
689 } | 690 } |
690 } | 691 } |
691 | 692 |
692 ProcessScoreMap new_map; | 693 ProcessScoreMap new_map; |
693 | 694 |
695 // Make the apps non-killable. | |
696 if (!apps_non_killable.empty()) | |
697 SetOomScore(apps_non_killable, kLowestOomScore, &new_map); | |
698 | |
694 // Higher priority part. | 699 // Higher priority part. |
695 DistributeOomScoreInRange(candidates.begin(), lower_priority_part, | 700 DistributeOomScoreInRange(candidates.begin(), lower_priority_part, |
696 chrome::kLowestRendererOomScore, range_middle, | 701 chrome::kLowestRendererOomScore, range_middle, |
697 &new_map); | 702 &new_map); |
698 // Lower priority part. | 703 // Lower priority part. |
699 DistributeOomScoreInRange(lower_priority_part, candidates.end(), range_middle, | 704 DistributeOomScoreInRange(lower_priority_part, candidates.end(), range_middle, |
700 chrome::kHighestRendererOomScore, &new_map); | 705 chrome::kHighestRendererOomScore, &new_map); |
706 | |
701 oom_score_map_.swap(new_map); | 707 oom_score_map_.swap(new_map); |
702 } | 708 } |
703 | 709 |
710 void TabManagerDelegate::SetOomScore( | |
711 const std::vector<TabManagerDelegate::Candidate>& candidates, | |
712 int score, | |
713 ProcessScoreMap* new_map) { | |
714 DistributeOomScoreInRange(candidates.begin(), candidates.end(), score - 1, | |
cylee1
2017/05/10 16:31:55
I'm confused: why is it score -1 ?
Yusuke Sato
2017/05/10 18:29:43
This is because of the rounding code at L737. Adde
cylee1
2017/05/11 08:59:53
Ah it's because of the round down of "negative" nu
Yusuke Sato
2017/05/11 18:50:16
Done.
Let me use round as this seems easier to re
| |
715 score - 1, new_map); | |
716 } | |
717 | |
704 void TabManagerDelegate::DistributeOomScoreInRange( | 718 void TabManagerDelegate::DistributeOomScoreInRange( |
705 std::vector<TabManagerDelegate::Candidate>::const_iterator begin, | 719 std::vector<TabManagerDelegate::Candidate>::const_iterator begin, |
706 std::vector<TabManagerDelegate::Candidate>::const_iterator end, | 720 std::vector<TabManagerDelegate::Candidate>::const_iterator end, |
707 int range_begin, | 721 int range_begin, |
708 int range_end, | 722 int range_end, |
709 ProcessScoreMap* new_map) { | 723 ProcessScoreMap* new_map) { |
710 // Processes whose OOM scores should be updated. Ignore duplicated pids but | 724 // Processes whose OOM scores should be updated. Ignore duplicated pids but |
711 // the last occurrence. | 725 // the last occurrence. |
712 std::map<base::ProcessHandle, int32_t> oom_scores_to_change; | 726 std::map<base::ProcessHandle, int32_t> oom_scores_to_change; |
713 | 727 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
752 } | 766 } |
753 priority += priority_increment; | 767 priority += priority_increment; |
754 } | 768 } |
755 | 769 |
756 if (oom_scores_to_change.size()) | 770 if (oom_scores_to_change.size()) |
757 GetDebugDaemonClient()->SetOomScoreAdj( | 771 GetDebugDaemonClient()->SetOomScoreAdj( |
758 oom_scores_to_change, base::Bind(&OnSetOomScoreAdj)); | 772 oom_scores_to_change, base::Bind(&OnSetOomScoreAdj)); |
759 } | 773 } |
760 | 774 |
761 } // namespace memory | 775 } // namespace memory |
OLD | NEW |