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 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 |