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 14 matching lines...) Expand all Loading... | |
25 #include "base/synchronization/lock.h" | 25 #include "base/synchronization/lock.h" |
26 #include "base/time/time.h" | 26 #include "base/time/time.h" |
27 #include "chrome/browser/chromeos/arc/arc_process.h" | 27 #include "chrome/browser/chromeos/arc/arc_process.h" |
28 #include "chrome/browser/chromeos/arc/arc_process_service.h" | 28 #include "chrome/browser/chromeos/arc/arc_process_service.h" |
29 #include "chrome/browser/memory/tab_stats.h" | 29 #include "chrome/browser/memory/tab_stats.h" |
30 #include "chrome/browser/ui/browser.h" | 30 #include "chrome/browser/ui/browser.h" |
31 #include "chrome/browser/ui/browser_list.h" | 31 #include "chrome/browser/ui/browser_list.h" |
32 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 32 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
33 #include "chrome/common/chrome_constants.h" | 33 #include "chrome/common/chrome_constants.h" |
34 #include "chrome/common/chrome_features.h" | 34 #include "chrome/common/chrome_features.h" |
35 #include "chromeos/dbus/dbus_thread_manager.h" | |
36 #include "chromeos/dbus/debug_daemon_client.h" | |
35 #include "components/arc/arc_bridge_service.h" | 37 #include "components/arc/arc_bridge_service.h" |
36 #include "components/arc/common/process.mojom.h" | 38 #include "components/arc/common/process.mojom.h" |
37 #include "components/arc/metrics/oom_kills_histogram.h" | 39 #include "components/arc/metrics/oom_kills_histogram.h" |
38 #include "components/exo/shell_surface.h" | 40 #include "components/exo/shell_surface.h" |
39 #include "content/public/browser/browser_thread.h" | 41 #include "content/public/browser/browser_thread.h" |
40 #include "content/public/browser/notification_service.h" | 42 #include "content/public/browser/notification_service.h" |
41 #include "content/public/browser/notification_types.h" | 43 #include "content/public/browser/notification_types.h" |
42 #include "content/public/browser/render_process_host.h" | 44 #include "content/public/browser/render_process_host.h" |
43 #include "content/public/browser/render_widget_host.h" | 45 #include "content/public/browser/render_widget_host.h" |
44 #include "content/public/browser/zygote_host_linux.h" | 46 #include "content/public/browser/zygote_host_linux.h" |
(...skipping 28 matching lines...) Expand all Loading... | |
73 return false; | 75 return false; |
74 std::string application_id = exo::ShellSurface::GetApplicationId(window); | 76 std::string application_id = exo::ShellSurface::GetApplicationId(window); |
75 return base::StartsWith(application_id, kArcProcessNamePrefix, | 77 return base::StartsWith(application_id, kArcProcessNamePrefix, |
76 base::CompareCase::SENSITIVE); | 78 base::CompareCase::SENSITIVE); |
77 } | 79 } |
78 | 80 |
79 bool IsArcMemoryManagementEnabled() { | 81 bool IsArcMemoryManagementEnabled() { |
80 return base::FeatureList::IsEnabled(features::kArcMemoryManagement); | 82 return base::FeatureList::IsEnabled(features::kArcMemoryManagement); |
81 } | 83 } |
82 | 84 |
85 void OnSetOomScoreAdj(bool success, const std::string& output) { | |
86 VLOG(2) << "OnSetOomScoreAdj " << success << " " << output; | |
87 if (!success || output != "") { | |
Georges Khalil
2016/08/15 18:47:54
nit: !output.empty()
nit: no braces
cylee1
2016/08/16 19:47:10
Done.
| |
88 LOG(WARNING) << "Set OOM score error: " << output; | |
89 } | |
90 } | |
91 | |
83 } // namespace | 92 } // namespace |
84 | 93 |
85 std::ostream& operator<<(std::ostream& os, const ProcessType& type) { | 94 std::ostream& operator<<(std::ostream& os, const ProcessType& type) { |
86 switch (type) { | 95 switch (type) { |
87 case ProcessType::FOCUSED_APP: | 96 case ProcessType::FOCUSED_APP: |
88 return os << "FOCUSED_APP/FOCUSED_TAB"; | 97 return os << "FOCUSED_APP/FOCUSED_TAB"; |
89 case ProcessType::VISIBLE_APP: | 98 case ProcessType::VISIBLE_APP: |
90 return os << "VISIBLE_APP"; | 99 return os << "VISIBLE_APP"; |
91 case ProcessType::BACKGROUND_APP: | 100 case ProcessType::BACKGROUND_APP: |
92 return os << "BACKGROUND_APP"; | 101 return os << "BACKGROUND_APP"; |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
480 // The focused process doesn't render a tab. Could happen when the focus | 489 // The focused process doesn't render a tab. Could happen when the focus |
481 // just switched to an ARC app. We can not avoid the race. | 490 // just switched to an ARC app. We can not avoid the race. |
482 if (pid == base::kNullProcessHandle) | 491 if (pid == base::kNullProcessHandle) |
483 return; | 492 return; |
484 { | 493 { |
485 base::AutoLock oom_score_autolock(oom_score_lock_); | 494 base::AutoLock oom_score_autolock(oom_score_lock_); |
486 oom_score_map_[pid] = chrome::kLowestRendererOomScore; | 495 oom_score_map_[pid] = chrome::kLowestRendererOomScore; |
487 } | 496 } |
488 VLOG(3) << "Set OOM score " << chrome::kLowestRendererOomScore | 497 VLOG(3) << "Set OOM score " << chrome::kLowestRendererOomScore |
489 << " for focused tab " << pid; | 498 << " for focused tab " << pid; |
490 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore( | 499 std::map<int, int> dict; |
491 pid, chrome::kLowestRendererOomScore); | 500 dict[pid] = chrome::kLowestRendererOomScore; |
501 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->SetOomScoreAdj( | |
502 dict, base::Bind(&OnSetOomScoreAdj)); | |
492 } | 503 } |
493 | 504 |
494 void TabManagerDelegate::OnFocusTabScoreAdjustmentTimeout() { | 505 void TabManagerDelegate::OnFocusTabScoreAdjustmentTimeout() { |
495 BrowserThread::PostTask( | 506 BrowserThread::PostTask( |
496 BrowserThread::FILE, FROM_HERE, | 507 BrowserThread::FILE, FROM_HERE, |
497 base::Bind(&TabManagerDelegate::AdjustFocusedTabScoreOnFileThread, | 508 base::Bind(&TabManagerDelegate::AdjustFocusedTabScoreOnFileThread, |
498 base::Unretained(this))); | 509 base::Unretained(this))); |
499 } | 510 } |
500 | 511 |
501 void TabManagerDelegate::AdjustFocusedTabScore(base::ProcessHandle pid) { | 512 void TabManagerDelegate::AdjustFocusedTabScore(base::ProcessHandle pid) { |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
739 DistributeOomScoreInRange(candidates.begin(), lower_priority_part, | 750 DistributeOomScoreInRange(candidates.begin(), lower_priority_part, |
740 chrome::kLowestRendererOomScore, range_middle, | 751 chrome::kLowestRendererOomScore, range_middle, |
741 &new_map); | 752 &new_map); |
742 // Lower priority part. | 753 // Lower priority part. |
743 DistributeOomScoreInRange(lower_priority_part, candidates.end(), range_middle, | 754 DistributeOomScoreInRange(lower_priority_part, candidates.end(), range_middle, |
744 chrome::kHighestRendererOomScore, &new_map); | 755 chrome::kHighestRendererOomScore, &new_map); |
745 base::AutoLock oom_score_autolock(oom_score_lock_); | 756 base::AutoLock oom_score_autolock(oom_score_lock_); |
746 oom_score_map_.swap(new_map); | 757 oom_score_map_.swap(new_map); |
747 } | 758 } |
748 | 759 |
749 void TabManagerDelegate::SetOomScoreAdjForApp(int nspid, int score) { | 760 void TabManagerDelegate::SetOomScoreAdj( |
750 if (!arc_process_instance_) | |
751 return; | |
752 if (arc_process_instance_version_ < 2) { | |
753 VLOG(1) << "ProcessInstance version < 2 does not " | |
754 "support SetOomScoreAdj() yet."; | |
755 return; | |
756 } | |
757 arc_process_instance_->SetOomScoreAdj(nspid, score); | |
758 } | |
759 | |
760 void TabManagerDelegate::SetOomScoreAdjForTabs( | |
761 const std::vector<std::pair<base::ProcessHandle, int>>& entries) { | 761 const std::vector<std::pair<base::ProcessHandle, int>>& entries) { |
762 BrowserThread::PostTask( | 762 BrowserThread::PostTask( |
763 BrowserThread::FILE, FROM_HERE, | 763 BrowserThread::FILE, FROM_HERE, |
764 base::Bind(&TabManagerDelegate::SetOomScoreAdjForTabsOnFileThread, | 764 base::Bind(&TabManagerDelegate::SetOomScoreAdjOnFileThread, |
765 base::Unretained(this), entries)); | 765 base::Unretained(this), entries)); |
766 } | 766 } |
767 | 767 |
768 void TabManagerDelegate::SetOomScoreAdjForTabsOnFileThread( | 768 // XXX: In the past it writes to procfs directly so running in file thread. |
769 // Now it talks to debugd via DBus and the write is done in debugd | |
770 // asynchronously. Consider moving it back to UI thread. | |
771 void TabManagerDelegate::SetOomScoreAdjOnFileThread( | |
769 const std::vector<std::pair<base::ProcessHandle, int>>& entries) { | 772 const std::vector<std::pair<base::ProcessHandle, int>>& entries) { |
770 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 773 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
771 for (const auto& entry : entries) { | 774 |
772 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore(entry.first, | 775 std::map<int, int> dict; |
773 entry.second); | 776 // Ignore duplicated keys but the last occurrence. |
774 } | 777 for (const auto& entry : entries) |
778 dict[entry.first] = entry.second; | |
779 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->SetOomScoreAdj( | |
hashimoto
2016/08/15 03:54:23
D-Bus clients are not thread-safe.
They must be ac
cylee1
2016/08/16 19:47:10
Done.
| |
780 dict, base::Bind(&OnSetOomScoreAdj)); | |
775 } | 781 } |
776 | 782 |
777 void TabManagerDelegate::DistributeOomScoreInRange( | 783 void TabManagerDelegate::DistributeOomScoreInRange( |
778 std::vector<TabManagerDelegate::Candidate>::const_iterator begin, | 784 std::vector<TabManagerDelegate::Candidate>::const_iterator begin, |
779 std::vector<TabManagerDelegate::Candidate>::const_iterator end, | 785 std::vector<TabManagerDelegate::Candidate>::const_iterator end, |
780 int range_begin, | 786 int range_begin, |
781 int range_end, | 787 int range_end, |
782 ProcessScoreMap* new_map) { | 788 ProcessScoreMap* new_map) { |
783 // OOM score setting for tabs involves file system operation so should be | 789 std::vector<std::pair<base::ProcessHandle, int>> oom_scores_to_change; |
784 // done on file thread. | |
785 std::vector<std::pair<base::ProcessHandle, int>> oom_score_for_tabs; | |
786 | 790 |
787 // Though there might be duplicate process handles, it doesn't matter to | 791 // Though there might be duplicate process handles, it doesn't matter to |
788 // overestimate the number of processes here since the we don't need to | 792 // overestimate the number of processes here since the we don't need to |
789 // use up the full range. | 793 // use up the full range. |
790 int num = (end - begin); | 794 int num = (end - begin); |
791 const float priority_increment = | 795 const float priority_increment = |
792 static_cast<float>(range_end - range_begin) / num; | 796 static_cast<float>(range_end - range_begin) / num; |
793 | 797 |
794 float priority = range_begin; | 798 float priority = range_begin; |
795 for (auto cur = begin; cur != end; ++cur) { | 799 for (auto cur = begin; cur != end; ++cur) { |
796 int score = static_cast<int>(priority + 0.5f); | 800 int score = static_cast<int>(priority + 0.5f); |
797 if (cur->app()) { | 801 if (cur->app()) { |
802 base::ProcessHandle pid = cur->app()->pid(); | |
798 // Use pid as map keys so it's globally unique. | 803 // Use pid as map keys so it's globally unique. |
799 (*new_map)[cur->app()->pid()] = score; | 804 (*new_map)[pid] = score; |
800 int cur_app_pid_score = 0; | 805 int cur_app_pid_score = 0; |
801 { | 806 { |
802 base::AutoLock oom_score_autolock(oom_score_lock_); | 807 base::AutoLock oom_score_autolock(oom_score_lock_); |
803 cur_app_pid_score = oom_score_map_[cur->app()->pid()]; | 808 cur_app_pid_score = oom_score_map_[pid]; |
804 } | 809 } |
805 if (cur_app_pid_score != score) { | 810 if (cur_app_pid_score != score) { |
806 VLOG(3) << "Set OOM score " << score << " for " << *cur; | 811 VLOG(3) << "Set OOM score " << score << " for " << *cur; |
807 SetOomScoreAdjForApp(cur->app()->nspid(), score); | 812 oom_scores_to_change.push_back(std::make_pair(pid, score)); |
808 } | 813 } |
809 } else { | 814 } else { |
810 base::ProcessHandle process_handle = cur->tab()->renderer_handle; | 815 base::ProcessHandle process_handle = cur->tab()->renderer_handle; |
811 // 1. tab_list contains entries for already-discarded tabs. If the PID | 816 // 1. tab_list contains entries for already-discarded tabs. If the PID |
812 // (renderer_handle) is zero, we don't need to adjust the oom_score. | 817 // (renderer_handle) is zero, we don't need to adjust the oom_score. |
813 // 2. Only add unseen process handle so if there's multiple tab maps to | 818 // 2. Only add unseen process handle so if there's multiple tab maps to |
814 // the same process, the process is set to an OOM score based on its "most | 819 // the same process, the process is set to an OOM score based on its "most |
815 // important" tab. | 820 // important" tab. |
816 if (process_handle != 0 && | 821 if (process_handle != 0 && |
817 new_map->find(process_handle) == new_map->end()) { | 822 new_map->find(process_handle) == new_map->end()) { |
818 (*new_map)[process_handle] = score; | 823 (*new_map)[process_handle] = score; |
819 int process_handle_score = 0; | 824 int process_handle_score = 0; |
820 { | 825 { |
821 base::AutoLock oom_score_autolock(oom_score_lock_); | 826 base::AutoLock oom_score_autolock(oom_score_lock_); |
822 process_handle_score = oom_score_map_[process_handle]; | 827 process_handle_score = oom_score_map_[process_handle]; |
823 } | 828 } |
824 if (process_handle_score != score) { | 829 if (process_handle_score != score) { |
825 oom_score_for_tabs.push_back(std::make_pair(process_handle, score)); | |
826 VLOG(3) << "Set OOM score " << score << " for " << *cur; | 830 VLOG(3) << "Set OOM score " << score << " for " << *cur; |
831 oom_scores_to_change.push_back(std::make_pair(process_handle, score)); | |
827 } | 832 } |
828 } else { | 833 } else { |
829 continue; // Skip priority increment. | 834 continue; // Skip priority increment. |
830 } | 835 } |
831 } | 836 } |
832 priority += priority_increment; | 837 priority += priority_increment; |
833 } | 838 } |
834 | 839 |
835 if (oom_score_for_tabs.size()) | 840 if (oom_scores_to_change.size()) |
836 SetOomScoreAdjForTabs(oom_score_for_tabs); | 841 SetOomScoreAdj(oom_scores_to_change); |
837 } | 842 } |
838 | 843 |
839 } // namespace memory | 844 } // namespace memory |
OLD | NEW |