Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(14)

Side by Side Diff: chrome/browser/memory/tab_manager_delegate_chromeos_unittest.cc

Issue 2095413002: TabManagerDelegate: Better prioritize ARC processes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <map> 8 #include <map>
9 #include <string> 9 #include <string>
10 #include <vector> 10 #include <vector>
11 11
12 #include "ash/shell.h" 12 #include "ash/shell.h"
13 #include "ash/test/ash_test_base.h" 13 #include "ash/test/ash_test_base.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/weak_ptr.h" 15 #include "base/memory/weak_ptr.h"
16 #include "base/process/process_handle.h" 16 #include "base/process/process_handle.h"
17 #include "chrome/browser/chromeos/arc/arc_process.h" 17 #include "chrome/browser/chromeos/arc/arc_process.h"
18 #include "chrome/browser/memory/arc_process_adj_level.h"
18 #include "chrome/browser/memory/tab_manager.h" 19 #include "chrome/browser/memory/tab_manager.h"
19 #include "chrome/browser/memory/tab_stats.h" 20 #include "chrome/browser/memory/tab_stats.h"
20 #include "chrome/common/url_constants.h" 21 #include "chrome/common/url_constants.h"
21 #include "components/arc/common/process.mojom.h" 22 #include "components/arc/common/process.mojom.h"
22 #include "components/arc/test/fake_arc_bridge_service.h" 23 #include "components/arc/test/fake_arc_bridge_service.h"
23 #include "components/exo/shell_surface.h" 24 #include "components/exo/shell_surface.h"
24 #include "testing/gtest/include/gtest/gtest.h" 25 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/aura/window.h" 26 #include "ui/aura/window.h"
26 #include "ui/wm/public/activation_client.h" 27 #include "ui/wm/public/activation_client.h"
27 #include "url/gurl.h" 28 #include "url/gurl.h"
28 29
29 namespace memory { 30 namespace memory {
30 31
31 namespace { 32 typedef testing::Test TabManagerDelegateTest;
32
33 const char kExoShellSurfaceWindowName[] = "ExoShellSurface";
34 const char kArcProcessNamePrefix[] = "org.chromium.arc.";
35
36 } // namespace
37
38 class TabManagerDelegateTest : public ash::test::AshTestBase {
39 public:
40 TabManagerDelegateTest() : application_id_(kArcProcessNamePrefix) {}
41 ~TabManagerDelegateTest() override {}
42
43 void SetUp() override {
44 AshTestBase::SetUp();
45
46 arc_window_ = CreateTestWindowInShellWithId(0);
47 arc_window_->SetName(kExoShellSurfaceWindowName);
48 exo::ShellSurface::SetApplicationId(arc_window_,
49 &application_id_);
50 }
51
52 protected:
53 void ActivateArcWindow() {
54 GetActivationClient()->ActivateWindow(arc_window_);
55 }
56 void DeactivateArcWindow() {
57 GetActivationClient()->DeactivateWindow(arc_window_);
58 }
59
60 private:
61 aura::client::ActivationClient* GetActivationClient() {
62 return aura::client::GetActivationClient(
63 ash::Shell::GetPrimaryRootWindow());
64 }
65
66 aura::Window* arc_window_;
67 std::string application_id_;
68 };
69 33
70 TEST_F(TabManagerDelegateTest, CandidatesSorted) { 34 TEST_F(TabManagerDelegateTest, CandidatesSorted) {
71 std::vector<arc::ArcProcess> arc_processes; 35 std::vector<arc::ArcProcess> arc_processes;
72 arc_processes.emplace_back(1, 10, "top", arc::mojom::ProcessState::TOP); 36 arc_processes.emplace_back(1, 10, "focused", arc::mojom::ProcessState::TOP,
73 arc_processes.emplace_back(2, 20, "foreground", 37 ArcProcessAdjLevel::FOREGROUND_APP_ADJ, 100);
74 arc::mojom::ProcessState::FOREGROUND_SERVICE); 38 arc_processes.emplace_back(2, 20, "visible1",
39 arc::mojom::ProcessState::FOREGROUND_SERVICE,
40 ArcProcessAdjLevel::VISIBLE_APP_ADJ, 200);
75 arc_processes.emplace_back(3, 30, "service", 41 arc_processes.emplace_back(3, 30, "service",
76 arc::mojom::ProcessState::SERVICE); 42 arc::mojom::ProcessState::SERVICE,
43 ArcProcessAdjLevel::SERVICE_ADJ, 500);
44 arc_processes.emplace_back(4, 40, "visible2",
45 arc::mojom::ProcessState::BOUND_FOREGROUND_SERVICE,
46 ArcProcessAdjLevel::VISIBLE_APP_ADJ, 150);
47
77 48
78 TabStats tab1, tab2, tab3, tab4, tab5; 49 TabStats tab1, tab2, tab3, tab4, tab5;
79 tab1.tab_contents_id = 100; 50 tab1.tab_contents_id = 100;
80 tab1.is_pinned = true; 51 tab1.is_pinned = true;
81 52
82 tab2.tab_contents_id = 200; 53 tab2.tab_contents_id = 200;
83 tab2.is_internal_page = true; 54 tab2.is_internal_page = true;
84 55
85 tab3.tab_contents_id = 300; 56 tab3.tab_contents_id = 300;
86 tab3.is_pinned = true; 57 tab3.is_pinned = true;
87 tab3.is_media = true; 58 tab3.is_media = true;
88 59
89 tab4.tab_contents_id = 400; 60 tab4.tab_contents_id = 400;
90 tab4.is_media = true; 61 tab4.is_media = true;
91 62
92 tab5.tab_contents_id = 500; 63 tab5.tab_contents_id = 500;
93 tab5.is_app = true; 64 tab5.is_app = true;
94 TabStatsList tab_list = { 65 TabStatsList tab_list = {
95 tab1, tab2, tab3, tab4, tab5 66 tab1, tab2, tab3, tab4, tab5
96 }; 67 };
97 68
98 std::vector<TabManagerDelegate::Candidate> candidates; 69 std::vector<TabManagerDelegate::Candidate> candidates;
99 70
100 // Case 1: ARC window in the foreground.
101 ActivateArcWindow();
102 candidates = TabManagerDelegate::GetSortedCandidates( 71 candidates = TabManagerDelegate::GetSortedCandidates(
103 tab_list, arc_processes); 72 tab_list, arc_processes);
104 EXPECT_EQ(8U, candidates.size()); 73 EXPECT_EQ(9U, candidates.size());
105 74
106 EXPECT_EQ("service", candidates[0].app->process_name()); 75 // focused app.
107 EXPECT_EQ("foreground", candidates[1].app->process_name()); 76 EXPECT_EQ("focused", candidates[0].app()->process_name());
77 // visible app 1, last_activity_time larger than visible app 2.
78 EXPECT_EQ("visible1", candidates[1].app()->process_name());
79 // visible app 2, last_activity_time less than visible app 1.
80 EXPECT_EQ("visible2", candidates[2].app()->process_name());
81 // pinned and media.
82 EXPECT_EQ(300, candidates[3].tab()->tab_contents_id);
83 // media.
84 EXPECT_EQ(400, candidates[4].tab()->tab_contents_id);
85 // pinned.
86 EXPECT_EQ(100, candidates[5].tab()->tab_contents_id);
87 // chrome app.
88 EXPECT_EQ(500, candidates[6].tab()->tab_contents_id);
108 // internal page. 89 // internal page.
109 EXPECT_EQ(200, candidates[2].tab->tab_contents_id); 90 EXPECT_EQ(200, candidates[7].tab()->tab_contents_id);
110 // chrome app. 91 // background service.
111 EXPECT_EQ(500, candidates[3].tab->tab_contents_id); 92 EXPECT_EQ("service", candidates[8].app()->process_name());
112 // pinned.
113 EXPECT_EQ(100, candidates[4].tab->tab_contents_id);
114 // media.
115 EXPECT_EQ(400, candidates[5].tab->tab_contents_id);
116 // pinned and media.
117 EXPECT_EQ(300, candidates[6].tab->tab_contents_id);
118 // ARC window is the active window, so top app has highest priority.
119 EXPECT_EQ("top", candidates[7].app->process_name());
120
121 // Case 2: ARC window in the background.
122 DeactivateArcWindow();
123 candidates = TabManagerDelegate::GetSortedCandidates(
124 tab_list, arc_processes);
125 EXPECT_EQ(8U, candidates.size());
126
127 EXPECT_EQ("service", candidates[0].app->process_name());
128 EXPECT_EQ("foreground", candidates[1].app->process_name());
129 // internal page.
130 EXPECT_EQ(200, candidates[2].tab->tab_contents_id);
131
132 // Chrome app and android app are tied, so both orders are correct.
133 if (candidates[3].is_arc_app) {
134 EXPECT_EQ("top", candidates[3].app->process_name());
135 // chrome app.
136 EXPECT_EQ(500, candidates[4].tab->tab_contents_id);
137 } else {
138 // chrome app.
139 EXPECT_EQ(500, candidates[3].tab->tab_contents_id);
140 EXPECT_EQ("top", candidates[4].app->process_name());
141 }
142
143 // pinned.
144 EXPECT_EQ(100, candidates[5].tab->tab_contents_id);
145 // media.
146 EXPECT_EQ(400, candidates[6].tab->tab_contents_id);
147 // pinned and media.
148 EXPECT_EQ(300, candidates[7].tab->tab_contents_id);
149 } 93 }
150 94
151 class MockTabManagerDelegate : public TabManagerDelegate { 95 class MockTabManagerDelegate : public TabManagerDelegate {
152 public: 96 public:
153 MockTabManagerDelegate(): TabManagerDelegate(nullptr) { 97 MockTabManagerDelegate(): TabManagerDelegate(nullptr) {
154 } 98 }
155 99
156 explicit MockTabManagerDelegate(TabManagerDelegate::MemoryStat* mem_stat) 100 explicit MockTabManagerDelegate(TabManagerDelegate::MemoryStat* mem_stat)
157 : TabManagerDelegate(nullptr, mem_stat) { 101 : TabManagerDelegate(nullptr, mem_stat) {
158 } 102 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
219 163
220 private: 164 private:
221 int target_memory_to_free_kb_; 165 int target_memory_to_free_kb_;
222 std::map<base::ProcessHandle, int> process_pss_; 166 std::map<base::ProcessHandle, int> process_pss_;
223 }; 167 };
224 168
225 TEST_F(TabManagerDelegateTest, SetOomScoreAdj) { 169 TEST_F(TabManagerDelegateTest, SetOomScoreAdj) {
226 arc::FakeArcBridgeService fake_arc_bridge_service; 170 arc::FakeArcBridgeService fake_arc_bridge_service;
227 MockTabManagerDelegate tab_manager_delegate; 171 MockTabManagerDelegate tab_manager_delegate;
228 172
229 ActivateArcWindow();
230 std::vector<arc::ArcProcess> arc_processes; 173 std::vector<arc::ArcProcess> arc_processes;
231 arc_processes.emplace_back(1, 10, "top", arc::mojom::ProcessState::TOP); 174 arc_processes.emplace_back(1, 10, "focused", arc::mojom::ProcessState::TOP,
232 arc_processes.emplace_back(2, 20, "foreground", 175 ArcProcessAdjLevel::FOREGROUND_APP_ADJ, 100);
233 arc::mojom::ProcessState::FOREGROUND_SERVICE); 176 arc_processes.emplace_back(2, 20, "visible1",
177 arc::mojom::ProcessState::FOREGROUND_SERVICE,
178 ArcProcessAdjLevel::VISIBLE_APP_ADJ, 200);
234 arc_processes.emplace_back(3, 30, "service", 179 arc_processes.emplace_back(3, 30, "service",
235 arc::mojom::ProcessState::SERVICE); 180 arc::mojom::ProcessState::SERVICE,
181 ArcProcessAdjLevel::SERVICE_ADJ, 500);
182 arc_processes.emplace_back(4, 40, "visible2",
183 arc::mojom::ProcessState::BOUND_FOREGROUND_SERVICE,
184 ArcProcessAdjLevel::VISIBLE_APP_ADJ, 150);
236 185
237 TabStats tab1, tab2, tab3, tab4, tab5; 186 TabStats tab1, tab2, tab3, tab4, tab5;
238 tab1.is_pinned = true; 187 tab1.is_pinned = true;
239 tab1.renderer_handle = 11; 188 tab1.renderer_handle = 11;
240 189
241 tab2.is_internal_page = true; 190 tab2.is_internal_page = true;
242 tab2.renderer_handle = 11; 191 tab2.renderer_handle = 11;
243 192
244 tab3.is_pinned = true; 193 tab3.is_pinned = true;
245 tab3.is_media = true; 194 tab3.is_media = true;
246 tab3.renderer_handle = 12; 195 tab3.renderer_handle = 12;
247 196
248 tab4.is_media = true; 197 tab4.is_media = true;
249 tab4.renderer_handle = 12; 198 tab4.renderer_handle = 12;
250 199
251 tab5.is_app = true; 200 tab5.is_app = true;
252 tab5.renderer_handle = 12; 201 tab5.renderer_handle = 12;
253 TabStatsList tab_list = {tab1, tab2, tab3, tab4, tab5}; 202 TabStatsList tab_list = {tab1, tab2, tab3, tab4, tab5};
254 203
255 // Sorted order: 204 // Sorted order:
256 // app "service" pid: 30 oom_socre_adj: 825 205 // app "focused" pid: 10
257 // app "foreground" pid: 20 oom_score_adj: 650 206 // app "visible1" pid: 20
258 // tab2 pid: 11 oom_socre_adj: 417 207 // app "visible2" pid: 40
259 // tab5 pid: 12 oom_score_adj: 358 208 // tab3 pid: 12
260 // tab1 pid: 11 oom_socre_adj: 417 209 // tab4 pid: 12
261 // tab4 pid: 12 oom_socre_adj: 358 210 // tab1 pid: 11
262 // tab3 pid: 12 oom_score_adj: 358 211 // tab5 pid: 12
263 // app "top" pid: 10 oom_score_adj: 300 212 // tab2 pid: 11
213 // app "service" pid: 30
264 tab_manager_delegate.AdjustOomPrioritiesImpl(tab_list, arc_processes); 214 tab_manager_delegate.AdjustOomPrioritiesImpl(tab_list, arc_processes);
265 auto& oom_score_map = tab_manager_delegate.oom_score_map_; 215 auto& oom_score_map = tab_manager_delegate.oom_score_map_;
266 216
267 EXPECT_EQ(5U, oom_score_map.size()); 217 EXPECT_EQ(6U, oom_score_map.size());
268 218
269 // Higher priority part. 219 // Higher priority part.
270 EXPECT_EQ(300, oom_score_map[10]); 220 EXPECT_EQ(300, oom_score_map[10]);
271 EXPECT_EQ(358, oom_score_map[12]); 221 EXPECT_EQ(344, oom_score_map[20]);
272 EXPECT_EQ(417, oom_score_map[11]); 222 EXPECT_EQ(388, oom_score_map[40]);
223 EXPECT_EQ(431, oom_score_map[12]);
224 EXPECT_EQ(475, oom_score_map[11]);
273 225
274 // Lower priority part. 226 // Lower priority part.
275 EXPECT_EQ(650, oom_score_map[20]); 227 EXPECT_EQ(650, oom_score_map[30]);
276 EXPECT_EQ(825, oom_score_map[30]);
277 } 228 }
278 229
279 TEST_F(TabManagerDelegateTest, KillMultipleProcesses) { 230 TEST_F(TabManagerDelegateTest, KillMultipleProcesses) {
280 arc::FakeArcBridgeService fake_arc_bridge_service; 231 arc::FakeArcBridgeService fake_arc_bridge_service;
281 232
282 // Not owned. 233 // Not owned.
283 MockMemoryStat* memory_stat = new MockMemoryStat(); 234 MockMemoryStat* memory_stat = new MockMemoryStat();
284 235
285 // Instantiate the mock instance. 236 // Instantiate the mock instance.
286 MockTabManagerDelegate tab_manager_delegate(memory_stat); 237 MockTabManagerDelegate tab_manager_delegate(memory_stat);
287 238
288 ActivateArcWindow();
289
290 std::vector<arc::ArcProcess> arc_processes; 239 std::vector<arc::ArcProcess> arc_processes;
291 arc_processes.emplace_back(10001, 100, "top", arc::mojom::ProcessState::TOP); 240 arc_processes.emplace_back(1, 10, "focused", arc::mojom::ProcessState::TOP,
292 arc_processes.emplace_back(10002, 200, "foreground", 241 ArcProcessAdjLevel::FOREGROUND_APP_ADJ, 100);
293 arc::mojom::ProcessState::FOREGROUND_SERVICE); 242 arc_processes.emplace_back(2, 20, "visible1",
294 arc_processes.emplace_back(10003, 300, "service", 243 arc::mojom::ProcessState::FOREGROUND_SERVICE,
295 arc::mojom::ProcessState::SERVICE); 244 ArcProcessAdjLevel::VISIBLE_APP_ADJ, 200);
245 arc_processes.emplace_back(3, 30, "service",
246 arc::mojom::ProcessState::SERVICE,
247 ArcProcessAdjLevel::SERVICE_ADJ, 500);
248 arc_processes.emplace_back(4, 40, "visible2",
249 arc::mojom::ProcessState::BOUND_FOREGROUND_SERVICE,
250 ArcProcessAdjLevel::VISIBLE_APP_ADJ, 150);
296 251
297 TabStats tab1, tab2, tab3, tab4, tab5; 252 TabStats tab1, tab2, tab3, tab4, tab5;
298 tab1.is_pinned = true; 253 tab1.is_pinned = true;
299 tab1.renderer_handle = 11; 254 tab1.renderer_handle = 11;
300 tab1.tab_contents_id = 1; 255 tab1.tab_contents_id = 1;
301 256
302 tab2.is_internal_page = true; 257 tab2.is_internal_page = true;
303 tab2.renderer_handle = 11; 258 tab2.renderer_handle = 11;
304 tab2.tab_contents_id = 2; 259 tab2.tab_contents_id = 2;
305 260
306 tab3.is_pinned = true; 261 tab3.is_pinned = true;
307 tab3.is_media = true; 262 tab3.is_media = true;
308 tab3.renderer_handle = 12; 263 tab3.renderer_handle = 12;
309 tab3.tab_contents_id = 3; 264 tab3.tab_contents_id = 3;
310 265
311 tab4.is_media = true; 266 tab4.is_media = true;
312 tab4.renderer_handle = 12; 267 tab4.renderer_handle = 12;
313 tab4.tab_contents_id = 4; 268 tab4.tab_contents_id = 4;
314 269
315 tab5.is_app = true; 270 tab5.is_app = true;
316 tab5.renderer_handle = 12; 271 tab5.renderer_handle = 12;
317 tab5.tab_contents_id = 5; 272 tab5.tab_contents_id = 5;
318 TabStatsList tab_list = {tab1, tab2, tab3, tab4, tab5}; 273 TabStatsList tab_list = {tab1, tab2, tab3, tab4, tab5};
319 274
320 // Sorted order: 275 // Sorted order:
321 // app "service" pid: 30 276 // app "focused" pid: 10 nspid 1
322 // app "foreground" pid: 20 277 // app "visible1" pid: 20 nspid 2
323 // tab2 pid: 11 278 // app "visible2" pid: 40 nspid 4
324 // tab5 pid: 12 279 // tab3 pid: 12 tab_contents_id 3
325 // tab1 pid: 11 280 // tab4 pid: 12 tab_contents_id 4
326 // tab4 pid: 12 281 // tab1 pid: 11 tab_contents_id 1
327 // tab3 pid: 12 282 // tab5 pid: 12 tab_contents_id 5
328 // app "top" pid: 10 283 // tab2 pid: 11 tab_contents_id 2
284 // app "service" pid: 30 nspid 3
329 memory_stat->SetTargetMemoryToFreeKB(250000); 285 memory_stat->SetTargetMemoryToFreeKB(250000);
330 // The 3 entities to be killed. 286 // Entities to be killed.
331 memory_stat->SetProcessPss(300, 10000); 287 memory_stat->SetProcessPss(30, 10000);
332 memory_stat->SetProcessPss(200, 200000); 288 memory_stat->SetProcessPss(11, 200000);
333 memory_stat->SetProcessPss(11, 50000); 289 memory_stat->SetProcessPss(12, 30000);
334 // Should not be used. 290 // Should not be used.
335 memory_stat->SetProcessPss(100, 30000); 291 memory_stat->SetProcessPss(40, 50000);
336 memory_stat->SetProcessPss(12, 100000); 292 memory_stat->SetProcessPss(20, 30000);
293 memory_stat->SetProcessPss(10, 100000);
337 294
338 tab_manager_delegate.LowMemoryKillImpl(tab_list, arc_processes); 295 tab_manager_delegate.LowMemoryKillImpl(tab_list, arc_processes);
339 296
340 auto killed_arc_processes = tab_manager_delegate.GetKilledArcProcesses(); 297 auto killed_arc_processes = tab_manager_delegate.GetKilledArcProcesses();
341 auto killed_tabs = tab_manager_delegate.GetKilledTabs(); 298 auto killed_tabs = tab_manager_delegate.GetKilledTabs();
342 299
343 EXPECT_EQ(2U, killed_arc_processes.size()); 300 // Killed apps and their nspid.
344 EXPECT_EQ(1U, killed_tabs.size()); 301 EXPECT_EQ(1U, killed_arc_processes.size());
345 302 EXPECT_EQ(3, killed_arc_processes[0]);
346 // nspid. 303 // Killed tabs and their content id.
347 EXPECT_EQ(10003, killed_arc_processes[0]); 304 // Note that process with pid 11 is counted twice. But so far I don't have a
348 EXPECT_EQ(10002, killed_arc_processes[1]); 305 // good way to estimate the memory freed if multiple tabs share one process.
349 // tab content id. 306 EXPECT_EQ(3U, killed_tabs.size());
350 EXPECT_EQ(2, killed_tabs[0]); 307 EXPECT_EQ(2, killed_tabs[0]);
308 EXPECT_EQ(5, killed_tabs[1]);
309 EXPECT_EQ(1, killed_tabs[2]);
351 } 310 }
352 311
353 } // namespace memory 312 } // namespace memory
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698