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 #ifndef CHROME_BROWSER_MEMORY_TAB_MANAGER_DELEGATE_CHROMEOS_H_ | 5 #ifndef CHROME_BROWSER_MEMORY_TAB_MANAGER_DELEGATE_CHROMEOS_H_ |
| 6 #define CHROME_BROWSER_MEMORY_TAB_MANAGER_DELEGATE_CHROMEOS_H_ | 6 #define CHROME_BROWSER_MEMORY_TAB_MANAGER_DELEGATE_CHROMEOS_H_ |
| 7 | 7 |
| 8 #include <memory> | 8 #include <memory> |
| 9 #include <utility> | 9 #include <utility> |
| 10 #include <vector> | 10 #include <vector> |
| 11 | 11 |
| 12 #include "base/containers/hash_tables.h" | 12 #include "base/containers/hash_tables.h" |
| 13 #include "base/gtest_prod_util.h" | 13 #include "base/gtest_prod_util.h" |
| 14 #include "base/logging.h" | |
| 14 #include "base/macros.h" | 15 #include "base/macros.h" |
| 15 #include "base/memory/weak_ptr.h" | 16 #include "base/memory/weak_ptr.h" |
| 16 #include "base/process/process.h" | 17 #include "base/process/process.h" |
| 17 #include "base/timer/timer.h" | 18 #include "base/timer/timer.h" |
| 18 #include "chrome/browser/chromeos/arc/arc_process.h" | 19 #include "chrome/browser/chromeos/arc/arc_process.h" |
| 19 #include "chrome/browser/memory/tab_manager.h" | 20 #include "chrome/browser/memory/tab_manager.h" |
| 20 #include "chrome/browser/memory/tab_stats.h" | 21 #include "chrome/browser/memory/tab_stats.h" |
| 21 #include "chrome/browser/ui/browser_list_observer.h" | 22 #include "chrome/browser/ui/browser_list_observer.h" |
| 22 #include "components/arc/arc_bridge_service.h" | 23 #include "components/arc/arc_bridge_service.h" |
| 24 #include "components/arc/common/process.mojom.h" | |
| 23 #include "components/arc/instance_holder.h" | 25 #include "components/arc/instance_holder.h" |
| 24 #include "content/public/browser/notification_observer.h" | 26 #include "content/public/browser/notification_observer.h" |
| 25 #include "content/public/browser/notification_registrar.h" | 27 #include "content/public/browser/notification_registrar.h" |
| 26 #include "ui/wm/public/activation_change_observer.h" | 28 #include "ui/wm/public/activation_change_observer.h" |
| 27 | 29 |
| 28 namespace memory { | 30 namespace memory { |
| 29 | 31 |
| 30 // The importance of tabs/apps. The lower the value, the more likely a process | 32 // Possible types of Apps/Tabs processes. From most important to least |
| 31 // is to be selected on memory pressure. The values is additive, for example, | 33 // important. |
| 32 // one tab could be of value (CHROME_NORMAL | CHROME_PINNED). | 34 enum ProcessType { |
|
Yusuke Sato
2016/07/15 00:55:05
enum class
?
cylee1
2016/07/15 17:31:13
Yes I can make it so, at the expense of overloadin
Luis Héctor Chávez
2016/07/15 18:10:06
I think it's fine to overload operator<<. You are
cylee1
2016/07/20 17:57:53
ok agree.
| |
| 33 // TODO(cylee): Refactor this CL so the prioritize logic is unified in | 35 // There can be only one process having process type "FOCUSED_APP" |
| 34 // TabManager. | 36 // or "FOCUSED_TAB" in the system at any give time (i.e., The focused window |
| 35 enum ProcessPriority { | 37 // could be either a chrome window or an Android app. But not both. |
| 36 // Processes on Android side which generally don't have an app window, and | 38 FOCUSED_APP = 1, |
| 37 // possibly be auto relaunched if killed. | 39 FOCUSED_TAB = FOCUSED_APP, |
| 38 ANDROID_BACKGROUND = 1, | |
| 39 ANDROID_SERVICE = 1 << 1, | |
| 40 ANDROID_CANT_SAVE_STATE = 1 << 2, | |
| 41 ANDROID_PERCEPTIBLE = 1 << 3, | |
| 42 ANDROID_VISIBLE = 1 << 4, | |
| 43 ANDROID_TOP_SLEEPING = 1 << 5, | |
| 44 ANDROID_FOREGROUND_SERVICE = 1 << 6, | |
| 45 ANDROID_FOREGROUND = 1 << 7, | |
| 46 // A chrome window can be one of the 3 exclusive types below: | |
| 47 // internal page, normal page, or chrome app. | |
| 48 CHROME_INTERNAL = 1 << 8, | |
| 49 CHROME_NORMAL = 1 << 9, | |
| 50 CHROME_APP = 1 << 10, | |
| 51 // An android app which is on top of screen from Android's point of view, | |
| 52 // but the app window is inactive from Chrome OS's point of view. | |
| 53 // Give it a higher priority then normal chrome tab since it could not be | |
| 54 // reloaded if killed. | |
| 55 ANDROID_TOP_INACTIVE = CHROME_APP, | |
| 56 // A chrome tab could have following 3 additional attributes | |
| 57 // (not exclusive). | |
| 58 CHROME_PINNED = 1 << 11, | |
| 59 CHROME_MEDIA = 1 << 12, | |
| 60 CHROME_CANT_SAVE_STATE = 1 << 13, | |
| 61 // The highest level of priority. Either a selected tab or an Android app in | |
| 62 // an active window. In theory there should be at most one process with this | |
| 63 // priority at a time, but at the time of writing Chrome couldn't get Android | |
| 64 // window stack info yet so there may be multiple Android apps be token as on | |
| 65 // top of screen for now. | |
| 66 CHROME_SELECTED = 1 << 14, | |
| 67 ANDROID_TOP = CHROME_SELECTED, | |
| 68 | 40 |
| 69 ANDROID_PERSISTENT = 1 << 30, | 41 VISIBLE_APP = 2, |
| 70 ANDROID_NON_EXISTS = 0x7FFFFFFF | 42 BACKGROUND_TAB = 3, |
| 43 BACKGROUND_APP = 4, | |
| 44 UNKNOWN_TYPE = 5, | |
| 71 }; | 45 }; |
| 72 | 46 |
| 73 // The Chrome OS TabManagerDelegate is responsible for keeping the | 47 // The Chrome OS TabManagerDelegate is responsible for keeping the |
| 74 // renderers' scores up to date in /proc/<pid>/oom_score_adj. | 48 // renderers' scores up to date in /proc/<pid>/oom_score_adj. |
| 75 // | 49 // |
| 76 // Note that AdjustOomPriorities will be called on the UI thread by | 50 // Note that AdjustOomPriorities will be called on the UI thread by |
| 77 // TabManager, but the actual work will take place on the file thread | 51 // TabManager, but the actual work will take place on the file thread |
| 78 // (see implementation of AdjustOomPriorities). | 52 // (see implementation of AdjustOomPriorities). |
| 79 class TabManagerDelegate | 53 class TabManagerDelegate |
| 80 : public arc::InstanceHolder<arc::mojom::ProcessInstance>::Observer, | 54 : public arc::InstanceHolder<arc::mojom::ProcessInstance>::Observer, |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 127 | 101 |
| 128 // Kills a tab. Returns true if the tab is killed successfully. | 102 // Kills a tab. Returns true if the tab is killed successfully. |
| 129 // Virtual for unit testing. | 103 // Virtual for unit testing. |
| 130 virtual bool KillTab(int64_t tab_id); | 104 virtual bool KillTab(int64_t tab_id); |
| 131 | 105 |
| 132 private: | 106 private: |
| 133 FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, CandidatesSorted); | 107 FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, CandidatesSorted); |
| 134 FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, KillMultipleProcesses); | 108 FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, KillMultipleProcesses); |
| 135 FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, SetOomScoreAdj); | 109 FRIEND_TEST_ALL_PREFIXES(TabManagerDelegateTest, SetOomScoreAdj); |
| 136 | 110 |
| 137 struct Candidate; | 111 class Candidate; |
| 138 class FocusedProcess; | 112 class FocusedProcess; |
| 139 class UmaReporter; | 113 class UmaReporter; |
| 140 | 114 |
| 141 friend std::ostream& operator<<(std::ostream& out, | 115 friend std::ostream& operator<<(std::ostream& out, |
| 142 const Candidate& candidate); | 116 const Candidate& candidate); |
| 143 | 117 |
| 144 // content::NotificationObserver: | 118 // content::NotificationObserver: |
| 145 void Observe(int type, | 119 void Observe(int type, |
| 146 const content::NotificationSource& source, | 120 const content::NotificationSource& source, |
| 147 const content::NotificationDetails& details) override; | 121 const content::NotificationDetails& details) override; |
| 148 | 122 |
| 149 // Pair to hold child process host id and ProcessHandle. | 123 // Pair to hold child process host id and ProcessHandle. |
| 150 typedef std::pair<int, base::ProcessHandle> ProcessInfo; | 124 typedef std::pair<int, base::ProcessHandle> ProcessInfo; |
| 151 | 125 |
| 152 // Cache OOM scores in memory. | 126 // Cache OOM scores in memory. |
| 153 typedef base::hash_map<base::ProcessHandle, int> ProcessScoreMap; | 127 typedef base::hash_map<base::ProcessHandle, int> ProcessScoreMap; |
| 154 | 128 |
| 155 // Get the list of candidates to kill, sorted by reversed importance. | 129 // Get the list of candidates to kill, sorted by importance descendingly. |
|
Luis Héctor Chávez
2016/07/15 01:29:24
nit: descending importance
cylee1
2016/07/15 17:31:13
Done.
| |
| 156 static std::vector<Candidate> GetSortedCandidates( | 130 static std::vector<Candidate> GetSortedCandidates( |
| 157 const TabStatsList& tab_list, | 131 const TabStatsList& tab_list, |
| 158 const std::vector<arc::ArcProcess>& arc_processes); | 132 const std::vector<arc::ArcProcess>& arc_processes); |
| 159 | 133 |
| 160 // Posts AdjustFocusedTabScore task to the file thread. | 134 // Posts AdjustFocusedTabScore task to the file thread. |
| 161 void OnFocusTabScoreAdjustmentTimeout(); | 135 void OnFocusTabScoreAdjustmentTimeout(); |
| 162 | 136 |
| 163 // Kills a process after getting all info of tabs and apps. | 137 // Kills a process after getting all info of tabs and apps. |
| 164 void LowMemoryKillImpl(const TabStatsList& tab_list, | 138 void LowMemoryKillImpl(const TabStatsList& tab_list, |
| 165 const std::vector<arc::ArcProcess>& arc_processes); | 139 const std::vector<arc::ArcProcess>& arc_processes); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 183 void SetOomScoreAdjForApp(int nspid, int score); | 157 void SetOomScoreAdjForApp(int nspid, int score); |
| 184 | 158 |
| 185 // Sets oom_score_adj for a list of tabs on the file thread. | 159 // Sets oom_score_adj for a list of tabs on the file thread. |
| 186 void SetOomScoreAdjForTabsOnFileThread( | 160 void SetOomScoreAdjForTabsOnFileThread( |
| 187 const std::vector<std::pair<base::ProcessHandle, int>>& entries); | 161 const std::vector<std::pair<base::ProcessHandle, int>>& entries); |
| 188 | 162 |
| 189 // Sets OOM score for processes in the range [|rbegin|, |rend|) to integers | 163 // Sets OOM score for processes in the range [|rbegin|, |rend|) to integers |
| 190 // distributed evenly in [|range_begin|, |range_end|). | 164 // distributed evenly in [|range_begin|, |range_end|). |
| 191 // The new score is set in |new_map|. | 165 // The new score is set in |new_map|. |
| 192 void DistributeOomScoreInRange( | 166 void DistributeOomScoreInRange( |
| 193 std::vector<TabManagerDelegate::Candidate>::reverse_iterator rbegin, | 167 std::vector<TabManagerDelegate::Candidate>::const_iterator begin, |
| 194 std::vector<TabManagerDelegate::Candidate>::reverse_iterator rend, | 168 std::vector<TabManagerDelegate::Candidate>::const_iterator end, |
| 195 int range_begin, | 169 int range_begin, |
| 196 int range_end, | 170 int range_end, |
| 197 ProcessScoreMap* new_map); | 171 ProcessScoreMap* new_map); |
| 198 | 172 |
| 199 // Initiates an oom priority adjustment. | 173 // Initiates an oom priority adjustment. |
| 200 void ScheduleEarlyOomPrioritiesAdjustment(); | 174 void ScheduleEarlyOomPrioritiesAdjustment(); |
| 201 | 175 |
| 202 // Holds a reference to the owning TabManager. | 176 // Holds a reference to the owning TabManager. |
| 203 const base::WeakPtr<TabManager> tab_manager_; | 177 const base::WeakPtr<TabManager> tab_manager_; |
| 204 | 178 |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 229 // Reports UMA histograms. | 203 // Reports UMA histograms. |
| 230 std::unique_ptr<UmaReporter> uma_; | 204 std::unique_ptr<UmaReporter> uma_; |
| 231 | 205 |
| 232 // Weak pointer factory used for posting tasks to other threads. | 206 // Weak pointer factory used for posting tasks to other threads. |
| 233 base::WeakPtrFactory<TabManagerDelegate> weak_ptr_factory_; | 207 base::WeakPtrFactory<TabManagerDelegate> weak_ptr_factory_; |
| 234 | 208 |
| 235 DISALLOW_COPY_AND_ASSIGN(TabManagerDelegate); | 209 DISALLOW_COPY_AND_ASSIGN(TabManagerDelegate); |
| 236 }; | 210 }; |
| 237 | 211 |
| 238 // On ARC enabled machines, either a tab or an app could be a possible | 212 // On ARC enabled machines, either a tab or an app could be a possible |
| 239 // victim of low memory kill process. This is a helper struct which holds a | 213 // victim of low memory kill process. This is a helper class which holds a |
| 240 // pointer to an app or a tab (but not both) to facilitate prioritizing the | 214 // pointer to an app or a tab (but not both) to facilitate prioritizing the |
| 241 // victims. | 215 // victims. |
| 242 struct TabManagerDelegate::Candidate { | 216 class TabManagerDelegate::Candidate { |
| 243 Candidate(const TabStats* _tab, int _priority) | 217 public: |
| 244 : tab(_tab), priority(_priority), is_arc_app(false) {} | 218 explicit Candidate(const TabStats* tab) |
| 245 Candidate(const arc::ArcProcess* _app, int _priority) | 219 : tab_(tab), app_(nullptr), process_type_(GetProcessType()) { |
| 246 : app(_app), priority(_priority), is_arc_app(true) {} | 220 } |
|
Yusuke Sato
2016/07/15 00:55:05
DCHECK(tab_)?
cylee1
2016/07/15 17:31:13
Done.
| |
| 221 explicit Candidate(const arc::ArcProcess* app) | |
| 222 : tab_(nullptr), app_(app), process_type_(GetProcessType()) { | |
| 223 } | |
|
Yusuke Sato
2016/07/15 00:55:05
DCHECK(app_)?
cylee1
2016/07/15 17:31:13
Done.
| |
| 247 | 224 |
| 248 bool operator<(const Candidate& rhs) const { return priority < rhs.priority; } | 225 // Higher priority first. |
| 226 bool operator<(const Candidate& rhs) const { | |
|
Yusuke Sato
2016/07/15 00:55:05
Can you move the implementation to .cc? The implem
cylee1
2016/07/15 17:31:13
Done.
| |
| 227 if (process_type() != rhs.process_type()) | |
| 228 return process_type() < rhs.process_type(); | |
| 229 if (app() && rhs.app()) | |
| 230 // Sort by (process_state, last_activity_time) pair. | |
| 231 // Smaller process_state value means higher priority as defined in | |
| 232 // Android. | |
| 233 // Larger last_activity_time means more recently used. | |
| 234 return std::make_pair(app()->process_state(), | |
|
Yusuke Sato
2016/07/15 00:55:05
What about adding CompareAppStats method to the ap
cylee1
2016/07/15 17:31:13
Moved to arc_process.cc .
| |
| 235 -app()->last_activity_time()) < | |
| 236 std::make_pair(rhs.app()->process_state(), | |
| 237 -rhs.app()->last_activity_time()); | |
| 238 if (tab() && rhs.tab()) | |
| 239 return TabManager::CompareTabStats(*tab(), *rhs.tab()); | |
| 240 // Impossible case. If app and tab are mixed in one process type, favor | |
| 241 // apps. | |
| 242 NOTREACHED() << "Undefined comparison between apps and tabs"; | |
| 243 return app(); | |
| 244 } | |
| 249 | 245 |
| 250 union { | 246 |
| 251 const TabStats* tab; | 247 const TabStats* tab() const { return tab_; } |
| 252 const arc::ArcProcess* app; | 248 const arc::ArcProcess* app() const { return app_; } |
| 253 }; | 249 ProcessType process_type() const { return process_type_; } |
| 254 int priority; | 250 |
| 255 bool is_arc_app; | 251 private: |
| 252 ProcessType GetProcessType() { | |
|
Yusuke Sato
2016/07/15 00:55:05
* This can be const.
* Or better, can you make thi
cylee1
2016/07/15 17:31:13
Can I just use a const ? Passing all its member so
Luis Héctor Chávez
2016/07/15 18:10:06
Can you at the very least call this GetProcessType
Yusuke Sato
2016/07/19 01:31:36
Yeah, please rename it then.
cylee1
2016/07/20 17:57:53
Done.
cylee1
2016/07/20 17:57:53
Done.
| |
| 253 if (app()) { | |
| 254 if (app()->is_focused()) | |
| 255 return ProcessType::FOCUSED_APP; | |
| 256 if (app()->process_state() == arc::mojom::ProcessState::TOP) | |
| 257 return ProcessType::VISIBLE_APP; | |
| 258 return ProcessType::BACKGROUND_APP; | |
| 259 } else if (tab()) { | |
| 260 if (tab()->is_selected) | |
| 261 return ProcessType::FOCUSED_TAB; | |
| 262 return ProcessType::BACKGROUND_TAB; | |
| 263 } | |
| 264 NOTREACHED() << "Unexpected process type"; | |
| 265 return ProcessType::UNKNOWN_TYPE; | |
| 266 } | |
| 267 | |
| 268 const TabStats* tab_; | |
| 269 const arc::ArcProcess* app_; | |
| 270 ProcessType process_type_; | |
|
Yusuke Sato
2016/07/15 00:55:05
can be const too.
cylee1
2016/07/15 17:31:13
Because this class must allow copy and assign (use
| |
| 256 }; | 271 }; |
|
Yusuke Sato
2016/07/15 00:55:05
DISALLOW_COPY_AND_ASSIGN is missing.
cylee1
2016/07/15 17:31:13
This is used in a STL vector so it needs to allow
Luis Héctor Chávez
2016/07/15 18:10:06
non-copyable classes can be used in STL vectors. T
cylee1
2016/07/20 17:57:53
OK you're right.
But do I need move() here given
cylee1
2016/07/22 22:18:43
I decided to drop the DISALLOW_COPY_AND_ASSIGN lin
Luis Héctor Chávez
2016/07/22 22:30:31
It should be slightly more efficient to make it no
cylee1
2016/07/22 23:14:40
Per IM discussion, reverted back to move assignmen
| |
| 257 | 272 |
| 258 // A thin wrapper over library process_metric.h to get memory status so unit | 273 // A thin wrapper over library process_metric.h to get memory status so unit |
| 259 // test get a chance to mock out. | 274 // test get a chance to mock out. |
| 260 class TabManagerDelegate::MemoryStat { | 275 class TabManagerDelegate::MemoryStat { |
| 261 public: | 276 public: |
| 262 MemoryStat() {} | 277 MemoryStat() {} |
| 263 virtual ~MemoryStat() {} | 278 virtual ~MemoryStat() {} |
| 264 | 279 |
| 265 // Returns target size of memory to free given current memory pressure and | 280 // Returns target size of memory to free given current memory pressure and |
| 266 // pre-configured low memory margin. | 281 // pre-configured low memory margin. |
| 267 virtual int TargetMemoryToFreeKB(); | 282 virtual int TargetMemoryToFreeKB(); |
| 268 | 283 |
| 269 // Returns estimated memory to be freed if the process |pid| is killed. | 284 // Returns estimated memory to be freed if the process |pid| is killed. |
| 270 virtual int EstimatedMemoryFreedKB(base::ProcessHandle pid); | 285 virtual int EstimatedMemoryFreedKB(base::ProcessHandle pid); |
| 271 | 286 |
| 272 private: | 287 private: |
| 273 // Returns the low memory margin system config. Low memory condition is | 288 // Returns the low memory margin system config. Low memory condition is |
| 274 // reported if available memory is under the number. | 289 // reported if available memory is under the number. |
| 275 static int LowMemoryMarginKB(); | 290 static int LowMemoryMarginKB(); |
| 276 | 291 |
| 277 // Reads in an integer. | 292 // Reads in an integer. |
| 278 static int ReadIntFromFile(const char* file_name, int default_val); | 293 static int ReadIntFromFile(const char* file_name, int default_val); |
| 279 }; | 294 }; |
| 280 | 295 |
| 281 } // namespace memory | 296 } // namespace memory |
| 282 | 297 |
| 283 #endif // CHROME_BROWSER_MEMORY_TAB_MANAGER_DELEGATE_CHROMEOS_H_ | 298 #endif // CHROME_BROWSER_MEMORY_TAB_MANAGER_DELEGATE_CHROMEOS_H_ |
| OLD | NEW |