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/resource_coordinator/tab_manager_delegate_chromeos.h" |
6 | 6 |
7 #include <math.h> | 7 #include <math.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 #include <map> | 11 #include <map> |
12 #include <vector> | 12 #include <vector> |
13 | 13 |
14 #include "ash/shell.h" | 14 #include "ash/shell.h" |
15 #include "base/bind.h" | 15 #include "base/bind.h" |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/files/file_path.h" | 17 #include "base/files/file_path.h" |
18 #include "base/files/file_util.h" | 18 #include "base/files/file_util.h" |
19 #include "base/memory/memory_pressure_monitor_chromeos.h" | 19 #include "base/memory/memory_pressure_monitor_chromeos.h" |
20 #include "base/metrics/histogram_macros.h" | 20 #include "base/metrics/histogram_macros.h" |
21 #include "base/process/process_handle.h" // kNullProcessHandle. | 21 #include "base/process/process_handle.h" // kNullProcessHandle. |
22 #include "base/process/process_metrics.h" | 22 #include "base/process/process_metrics.h" |
23 #include "base/strings/string16.h" | 23 #include "base/strings/string16.h" |
24 #include "base/strings/string_number_conversions.h" | 24 #include "base/strings/string_number_conversions.h" |
25 #include "base/strings/string_util.h" | 25 #include "base/strings/string_util.h" |
26 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
27 #include "base/time/time.h" | 27 #include "base/time/time.h" |
28 #include "chrome/browser/chromeos/arc/process/arc_process.h" | 28 #include "chrome/browser/chromeos/arc/process/arc_process.h" |
29 #include "chrome/browser/chromeos/arc/process/arc_process_service.h" | 29 #include "chrome/browser/chromeos/arc/process/arc_process_service.h" |
30 #include "chrome/browser/memory/memory_kills_monitor.h" | 30 #include "chrome/browser/memory/memory_kills_monitor.h" |
31 #include "chrome/browser/memory/tab_stats.h" | 31 #include "chrome/browser/resource_coordinator/tab_stats.h" |
32 #include "chrome/browser/ui/browser.h" | 32 #include "chrome/browser/ui/browser.h" |
33 #include "chrome/browser/ui/browser_list.h" | 33 #include "chrome/browser/ui/browser_list.h" |
34 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 34 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
35 #include "chrome/common/chrome_constants.h" | 35 #include "chrome/common/chrome_constants.h" |
36 #include "chrome/common/chrome_features.h" | 36 #include "chrome/common/chrome_features.h" |
37 #include "chromeos/dbus/dbus_thread_manager.h" | 37 #include "chromeos/dbus/dbus_thread_manager.h" |
38 #include "components/arc/arc_bridge_service.h" | 38 #include "components/arc/arc_bridge_service.h" |
39 #include "components/arc/arc_service_manager.h" | 39 #include "components/arc/arc_service_manager.h" |
40 #include "components/arc/arc_util.h" | 40 #include "components/arc/arc_util.h" |
41 #include "components/device_event_log/device_event_log.h" | 41 #include "components/device_event_log/device_event_log.h" |
42 #include "content/public/browser/browser_thread.h" | 42 #include "content/public/browser/browser_thread.h" |
43 #include "content/public/browser/notification_service.h" | 43 #include "content/public/browser/notification_service.h" |
44 #include "content/public/browser/notification_types.h" | 44 #include "content/public/browser/notification_types.h" |
45 #include "content/public/browser/render_process_host.h" | 45 #include "content/public/browser/render_process_host.h" |
46 #include "content/public/browser/render_widget_host.h" | 46 #include "content/public/browser/render_widget_host.h" |
47 #include "content/public/browser/zygote_host_linux.h" | 47 #include "content/public/browser/zygote_host_linux.h" |
48 #include "ui/wm/public/activation_client.h" | 48 #include "ui/wm/public/activation_client.h" |
49 | 49 |
50 using base::ProcessHandle; | 50 using base::ProcessHandle; |
51 using base::TimeDelta; | 51 using base::TimeDelta; |
52 using base::TimeTicks; | 52 using base::TimeTicks; |
53 using content::BrowserThread; | 53 using content::BrowserThread; |
54 | 54 |
55 namespace memory { | 55 namespace resource_coordinator { |
56 namespace { | 56 namespace { |
57 | 57 |
58 // When switching to a new tab the tab's renderer's OOM score needs to be | 58 // When switching to a new tab the tab's renderer's OOM score needs to be |
59 // updated to reflect its front-most status and protect it from discard. | 59 // updated to reflect its front-most status and protect it from discard. |
60 // However, doing this immediately might slow down tab switch time, so wait | 60 // However, doing this immediately might slow down tab switch time, so wait |
61 // a little while before doing the adjustment. | 61 // a little while before doing the adjustment. |
62 const int kFocusedProcessScoreAdjustIntervalMs = 500; | 62 const int kFocusedProcessScoreAdjustIntervalMs = 500; |
63 | 63 |
64 wm::ActivationClient* GetActivationClient() { | 64 wm::ActivationClient* GetActivationClient() { |
65 if (!ash::Shell::HasInstance()) | 65 if (!ash::Shell::HasInstance()) |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
98 return os << "BACKGROUND_APP"; | 98 return os << "BACKGROUND_APP"; |
99 case ProcessType::UNKNOWN_TYPE: | 99 case ProcessType::UNKNOWN_TYPE: |
100 return os << "UNKNOWN_TYPE"; | 100 return os << "UNKNOWN_TYPE"; |
101 default: | 101 default: |
102 return os << "NOT_IMPLEMENTED_ERROR"; | 102 return os << "NOT_IMPLEMENTED_ERROR"; |
103 } | 103 } |
104 return os; | 104 return os; |
105 } | 105 } |
106 | 106 |
107 // TabManagerDelegate::Candidate implementation. | 107 // TabManagerDelegate::Candidate implementation. |
108 std::ostream& operator<<( | 108 std::ostream& operator<<(std::ostream& out, |
109 std::ostream& out, const TabManagerDelegate::Candidate& candidate) { | 109 const TabManagerDelegate::Candidate& candidate) { |
110 if (candidate.app()) { | 110 if (candidate.app()) { |
111 out << "app " << *candidate.app(); | 111 out << "app " << *candidate.app(); |
112 } else if (candidate.tab()) { | 112 } else if (candidate.tab()) { |
113 const TabStats* const& tab = candidate.tab(); | 113 const TabStats* const& tab = candidate.tab(); |
114 out << "tab " << tab->title << ", renderer_handle: " << tab->renderer_handle | 114 out << "tab " << tab->title << ", renderer_handle: " << tab->renderer_handle |
115 << ", oom_score: " << tab->oom_score | 115 << ", oom_score: " << tab->oom_score |
116 << ", is_discarded: " << tab->is_discarded | 116 << ", is_discarded: " << tab->is_discarded |
117 << ", discard_count: " << tab->discard_count | 117 << ", discard_count: " << tab->discard_count |
118 << ", last_active: " << tab->last_active; | 118 << ", last_active: " << tab->last_active; |
119 } | 119 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 | 207 |
208 // If a chrome tab. | 208 // If a chrome tab. |
209 base::ProcessHandle pid_; | 209 base::ProcessHandle pid_; |
210 // If an Android app. | 210 // If an Android app. |
211 int nspid_; | 211 int nspid_; |
212 }; | 212 }; |
213 | 213 |
214 // TabManagerDelegate::MemoryStat implementation. | 214 // TabManagerDelegate::MemoryStat implementation. |
215 | 215 |
216 // static | 216 // static |
217 int TabManagerDelegate::MemoryStat::ReadIntFromFile( | 217 int TabManagerDelegate::MemoryStat::ReadIntFromFile(const char* file_name, |
218 const char* file_name, const int default_val) { | 218 const int default_val) { |
219 std::string file_string; | 219 std::string file_string; |
220 if (!base::ReadFileToString(base::FilePath(file_name), &file_string)) { | 220 if (!base::ReadFileToString(base::FilePath(file_name), &file_string)) { |
221 LOG(WARNING) << "Unable to read file" << file_name; | 221 LOG(WARNING) << "Unable to read file" << file_name; |
222 return default_val; | 222 return default_val; |
223 } | 223 } |
224 int val = default_val; | 224 int val = default_val; |
225 if (!base::StringToInt( | 225 if (!base::StringToInt( |
226 base::TrimWhitespaceASCII(file_string, base::TRIM_TRAILING), | 226 base::TrimWhitespaceASCII(file_string, base::TRIM_TRAILING), &val)) { |
227 &val)) { | |
228 LOG(WARNING) << "Unable to parse string" << file_string; | 227 LOG(WARNING) << "Unable to parse string" << file_string; |
229 return default_val; | 228 return default_val; |
230 } | 229 } |
231 return val; | 230 return val; |
232 } | 231 } |
233 | 232 |
234 // static | 233 // static |
235 int TabManagerDelegate::MemoryStat::LowMemoryMarginKB() { | 234 int TabManagerDelegate::MemoryStat::LowMemoryMarginKB() { |
236 static const int kDefaultLowMemoryMarginMb = 50; | 235 static const int kDefaultLowMemoryMarginMb = 50; |
237 static const char kLowMemoryMarginConfig[] = | 236 static const char kLowMemoryMarginConfig[] = |
238 "/sys/kernel/mm/chromeos-low_mem/margin"; | 237 "/sys/kernel/mm/chromeos-low_mem/margin"; |
239 return ReadIntFromFile( | 238 return ReadIntFromFile(kLowMemoryMarginConfig, kDefaultLowMemoryMarginMb) * |
240 kLowMemoryMarginConfig, kDefaultLowMemoryMarginMb) * 1024; | 239 1024; |
241 } | 240 } |
242 | 241 |
243 // The logic of available memory calculation is copied from | 242 // The logic of available memory calculation is copied from |
244 // _is_low_mem_situation() in kernel file include/linux/low-mem-notify.h. | 243 // _is_low_mem_situation() in kernel file include/linux/low-mem-notify.h. |
245 // Maybe we should let kernel report the number directly. | 244 // Maybe we should let kernel report the number directly. |
246 int TabManagerDelegate::MemoryStat::TargetMemoryToFreeKB() { | 245 int TabManagerDelegate::MemoryStat::TargetMemoryToFreeKB() { |
247 static const int kRamVsSwapWeight = 4; | 246 static const int kRamVsSwapWeight = 4; |
248 static const char kMinFilelistConfig[] = "/proc/sys/vm/min_filelist_kbytes"; | 247 static const char kMinFilelistConfig[] = "/proc/sys/vm/min_filelist_kbytes"; |
249 static const char kMinFreeKbytes[] = "/proc/sys/vm/min_free_kbytes"; | 248 static const char kMinFreeKbytes[] = "/proc/sys/vm/min_free_kbytes"; |
250 | 249 |
251 base::SystemMemoryInfoKB system_mem; | 250 base::SystemMemoryInfoKB system_mem; |
252 base::GetSystemMemoryInfo(&system_mem); | 251 base::GetSystemMemoryInfo(&system_mem); |
253 const int file_mem_kb = system_mem.active_file + system_mem.inactive_file; | 252 const int file_mem_kb = system_mem.active_file + system_mem.inactive_file; |
254 const int min_filelist_kb = ReadIntFromFile(kMinFilelistConfig, 0); | 253 const int min_filelist_kb = ReadIntFromFile(kMinFilelistConfig, 0); |
255 const int min_free_kb = ReadIntFromFile(kMinFreeKbytes, 0); | 254 const int min_free_kb = ReadIntFromFile(kMinFreeKbytes, 0); |
256 // Calculate current available memory in system. | 255 // Calculate current available memory in system. |
257 // File-backed memory should be easy to reclaim, unless they're dirty. | 256 // File-backed memory should be easy to reclaim, unless they're dirty. |
258 // TODO(cylee): On ChromeOS, kernel reports low memory condition when | 257 // TODO(cylee): On ChromeOS, kernel reports low memory condition when |
259 // available memory is low. The following formula duplicates the logic in | 258 // available memory is low. The following formula duplicates the logic in |
260 // kernel to calculate how much memory should be released. In the future, | 259 // kernel to calculate how much memory should be released. In the future, |
261 // kernel should try to report the amount of memory to release directly to | 260 // kernel should try to report the amount of memory to release directly to |
262 // eliminate the duplication here. | 261 // eliminate the duplication here. |
263 const int available_mem_kb = system_mem.free + | 262 const int available_mem_kb = |
264 file_mem_kb - system_mem.dirty - min_filelist_kb + | 263 system_mem.free + file_mem_kb - system_mem.dirty - min_filelist_kb + |
265 system_mem.swap_free / kRamVsSwapWeight - | 264 system_mem.swap_free / kRamVsSwapWeight - min_free_kb; |
266 min_free_kb; | |
267 | 265 |
268 return LowMemoryMarginKB() - available_mem_kb; | 266 return LowMemoryMarginKB() - available_mem_kb; |
269 } | 267 } |
270 | 268 |
271 int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB( | 269 int TabManagerDelegate::MemoryStat::EstimatedMemoryFreedKB( |
272 base::ProcessHandle pid) { | 270 base::ProcessHandle pid) { |
273 std::unique_ptr<base::ProcessMetrics> process_metrics( | 271 std::unique_ptr<base::ProcessMetrics> process_metrics( |
274 base::ProcessMetrics::CreateProcessMetrics(pid)); | 272 base::ProcessMetrics::CreateProcessMetrics(pid)); |
275 base::WorkingSetKBytes mem_usage; | 273 base::WorkingSetKBytes mem_usage; |
276 process_metrics->GetWorkingSetKBytes(&mem_usage); | 274 process_metrics->GetWorkingSetKBytes(&mem_usage); |
277 return mem_usage.priv; | 275 return mem_usage.priv; |
278 } | 276 } |
279 | 277 |
280 TabManagerDelegate::TabManagerDelegate( | 278 TabManagerDelegate::TabManagerDelegate( |
281 const base::WeakPtr<TabManager>& tab_manager) | 279 const base::WeakPtr<TabManager>& tab_manager) |
282 : TabManagerDelegate(tab_manager, new MemoryStat()) { | 280 : TabManagerDelegate(tab_manager, new MemoryStat()) {} |
283 } | |
284 | 281 |
285 TabManagerDelegate::TabManagerDelegate( | 282 TabManagerDelegate::TabManagerDelegate( |
286 const base::WeakPtr<TabManager>& tab_manager, | 283 const base::WeakPtr<TabManager>& tab_manager, |
287 TabManagerDelegate::MemoryStat* mem_stat) | 284 TabManagerDelegate::MemoryStat* mem_stat) |
288 : tab_manager_(tab_manager), | 285 : tab_manager_(tab_manager), |
289 focused_process_(new FocusedProcess()), | 286 focused_process_(new FocusedProcess()), |
290 mem_stat_(mem_stat), | 287 mem_stat_(mem_stat), |
291 weak_ptr_factory_(this) { | 288 weak_ptr_factory_(this) { |
292 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, | 289 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, |
293 content::NotificationService::AllBrowserContextsAndSources()); | 290 content::NotificationService::AllBrowserContextsAndSources()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 // window, so schedule an early adjustment for all processes to reflect | 330 // window, so schedule an early adjustment for all processes to reflect |
334 // the change. | 331 // the change. |
335 // Put a dummy FocusedProcess with nspid = kInvalidArcAppNspid for now to | 332 // Put a dummy FocusedProcess with nspid = kInvalidArcAppNspid for now to |
336 // indicate the focused process is an arc app. | 333 // indicate the focused process is an arc app. |
337 // TODO(cylee): Fix it when we have nspid info in ARC windows. | 334 // TODO(cylee): Fix it when we have nspid info in ARC windows. |
338 focused_process_->SetArcAppNspid(FocusedProcess::kInvalidArcAppNspid); | 335 focused_process_->SetArcAppNspid(FocusedProcess::kInvalidArcAppNspid); |
339 // If the timer is already running (possibly for a tab), it'll be reset | 336 // If the timer is already running (possibly for a tab), it'll be reset |
340 // here. | 337 // here. |
341 focus_process_score_adjust_timer_.Start( | 338 focus_process_score_adjust_timer_.Start( |
342 FROM_HERE, | 339 FROM_HERE, |
343 TimeDelta::FromMilliseconds(kFocusedProcessScoreAdjustIntervalMs), | 340 TimeDelta::FromMilliseconds(kFocusedProcessScoreAdjustIntervalMs), this, |
344 this, &TabManagerDelegate::ScheduleEarlyOomPrioritiesAdjustment); | 341 &TabManagerDelegate::ScheduleEarlyOomPrioritiesAdjustment); |
345 } | 342 } |
346 if (arc::IsArcAppWindow(lost_active)) { | 343 if (arc::IsArcAppWindow(lost_active)) { |
347 // Do not bother adjusting OOM score if the ARC window is deactivated | 344 // Do not bother adjusting OOM score if the ARC window is deactivated |
348 // shortly. | 345 // shortly. |
349 if (focused_process_->ResetIfIsArcApp() && | 346 if (focused_process_->ResetIfIsArcApp() && |
350 focus_process_score_adjust_timer_.IsRunning()) | 347 focus_process_score_adjust_timer_.IsRunning()) |
351 focus_process_score_adjust_timer_.Stop(); | 348 focus_process_score_adjust_timer_.Stop(); |
352 } | 349 } |
353 } | 350 } |
354 | 351 |
355 void TabManagerDelegate::ScheduleEarlyOomPrioritiesAdjustment() { | 352 void TabManagerDelegate::ScheduleEarlyOomPrioritiesAdjustment() { |
356 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 353 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
357 if (tab_manager_) { | 354 if (tab_manager_) { |
358 AdjustOomPriorities(tab_manager_->GetUnsortedTabStats()); | 355 AdjustOomPriorities(tab_manager_->GetUnsortedTabStats()); |
359 } | 356 } |
360 } | 357 } |
361 | 358 |
362 // If able to get the list of ARC procsses, prioritize tabs and apps as a whole. | 359 // If able to get the list of ARC procsses, prioritize tabs and apps as a whole. |
363 // Otherwise try to kill tabs only. | 360 // Otherwise try to kill tabs only. |
364 void TabManagerDelegate::LowMemoryKill( | 361 void TabManagerDelegate::LowMemoryKill(const TabStatsList& tab_list) { |
365 const TabStatsList& tab_list) { | |
366 arc::ArcProcessService* arc_process_service = arc::ArcProcessService::Get(); | 362 arc::ArcProcessService* arc_process_service = arc::ArcProcessService::Get(); |
367 if (arc_process_service && | 363 if (arc_process_service && |
368 arc_process_service->RequestAppProcessList( | 364 arc_process_service->RequestAppProcessList( |
369 base::Bind(&TabManagerDelegate::LowMemoryKillImpl, | 365 base::Bind(&TabManagerDelegate::LowMemoryKillImpl, |
370 weak_ptr_factory_.GetWeakPtr(), tab_list))) { | 366 weak_ptr_factory_.GetWeakPtr(), tab_list))) { |
371 // LowMemoryKillImpl will be called asynchronously so nothing left to do. | 367 // LowMemoryKillImpl will be called asynchronously so nothing left to do. |
372 return; | 368 return; |
373 } | 369 } |
374 // If the list of ARC processes is not available, call LowMemoryKillImpl | 370 // If the list of ARC processes is not available, call LowMemoryKillImpl |
375 // synchronously with an empty list of apps. | 371 // synchronously with an empty list of apps. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 it->second != chrome::kLowestRendererOomScore); | 418 it->second != chrome::kLowestRendererOomScore); |
423 | 419 |
424 if (not_lowest_score) { | 420 if (not_lowest_score) { |
425 // By starting a timer we guarantee that the tab is focused for | 421 // By starting a timer we guarantee that the tab is focused for |
426 // certain amount of time. Secondly, it also does not add overhead | 422 // certain amount of time. Secondly, it also does not add overhead |
427 // to the tab switching time. | 423 // to the tab switching time. |
428 // If there's an existing running timer (could be for ARC app), it | 424 // If there's an existing running timer (could be for ARC app), it |
429 // would be replaced by a new task. | 425 // would be replaced by a new task. |
430 focus_process_score_adjust_timer_.Start( | 426 focus_process_score_adjust_timer_.Start( |
431 FROM_HERE, | 427 FROM_HERE, |
432 TimeDelta::FromMilliseconds(kFocusedProcessScoreAdjustIntervalMs), | 428 TimeDelta::FromMilliseconds(kFocusedProcessScoreAdjustIntervalMs), this, |
433 this, &TabManagerDelegate::OnFocusTabScoreAdjustmentTimeout); | 429 &TabManagerDelegate::OnFocusTabScoreAdjustmentTimeout); |
434 } | 430 } |
435 } | 431 } |
436 | 432 |
437 void TabManagerDelegate::Observe(int type, | 433 void TabManagerDelegate::Observe(int type, |
438 const content::NotificationSource& source, | 434 const content::NotificationSource& source, |
439 const content::NotificationDetails& details) { | 435 const content::NotificationDetails& details) { |
440 switch (type) { | 436 switch (type) { |
441 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: | 437 case content::NOTIFICATION_RENDERER_PROCESS_CLOSED: |
442 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { | 438 case content::NOTIFICATION_RENDERER_PROCESS_TERMINATED: { |
443 content::RenderProcessHost* host = | 439 content::RenderProcessHost* host = |
(...skipping 12 matching lines...) Expand all Loading... |
456 base::chromeos::MemoryPressureMonitor::Get(); | 452 base::chromeos::MemoryPressureMonitor::Get(); |
457 if (monitor) | 453 if (monitor) |
458 monitor->ScheduleEarlyCheck(); | 454 monitor->ScheduleEarlyCheck(); |
459 break; | 455 break; |
460 } | 456 } |
461 case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: { | 457 case content::NOTIFICATION_RENDER_WIDGET_VISIBILITY_CHANGED: { |
462 bool visible = *content::Details<bool>(details).ptr(); | 458 bool visible = *content::Details<bool>(details).ptr(); |
463 if (visible) { | 459 if (visible) { |
464 content::RenderProcessHost* render_host = | 460 content::RenderProcessHost* render_host = |
465 content::Source<content::RenderWidgetHost>(source) | 461 content::Source<content::RenderWidgetHost>(source) |
466 .ptr() | 462 .ptr() |
467 ->GetProcess(); | 463 ->GetProcess(); |
468 AdjustFocusedTabScore(render_host->GetHandle()); | 464 AdjustFocusedTabScore(render_host->GetHandle()); |
469 } | 465 } |
470 // Do not handle the "else" case when it changes to invisible because | 466 // Do not handle the "else" case when it changes to invisible because |
471 // 1. The behavior is a bit awkward in that when switching from tab A to | 467 // 1. The behavior is a bit awkward in that when switching from tab A to |
472 // tab B, the event "invisible of B" comes after "visible of A". It can | 468 // tab B, the event "invisible of B" comes after "visible of A". It can |
473 // cause problems when the 2 tabs have the same content (e.g., New Tab | 469 // cause problems when the 2 tabs have the same content (e.g., New Tab |
474 // Page). To be more clear, if we try to cancel the timer when losing | 470 // Page). To be more clear, if we try to cancel the timer when losing |
475 // focus it may cancel the timer for the same renderer process. | 471 // focus it may cancel the timer for the same renderer process. |
476 // 2. When another window is launched on top of an existing browser | 472 // 2. When another window is launched on top of an existing browser |
477 // window, the selected tab in the existing browser didn't receive this | 473 // window, the selected tab in the existing browser didn't receive this |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 arc_service_manager->arc_bridge_service()->process(), KillProcess); | 546 arc_service_manager->arc_bridge_service()->process(), KillProcess); |
551 if (!arc_process_instance) | 547 if (!arc_process_instance) |
552 return false; | 548 return false; |
553 | 549 |
554 arc_process_instance->KillProcess(nspid, "LowMemoryKill"); | 550 arc_process_instance->KillProcess(nspid, "LowMemoryKill"); |
555 return true; | 551 return true; |
556 } | 552 } |
557 | 553 |
558 bool TabManagerDelegate::KillTab(int64_t tab_id) { | 554 bool TabManagerDelegate::KillTab(int64_t tab_id) { |
559 // Check |tab_manager_| is alive before taking tabs into consideration. | 555 // Check |tab_manager_| is alive before taking tabs into consideration. |
560 return tab_manager_ && | 556 return tab_manager_ && tab_manager_->CanDiscardTab(tab_id) && |
561 tab_manager_->CanDiscardTab(tab_id) && | 557 tab_manager_->DiscardTabById(tab_id); |
562 tab_manager_->DiscardTabById(tab_id); | |
563 } | 558 } |
564 | 559 |
565 | |
566 chromeos::DebugDaemonClient* TabManagerDelegate::GetDebugDaemonClient() { | 560 chromeos::DebugDaemonClient* TabManagerDelegate::GetDebugDaemonClient() { |
567 return chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); | 561 return chromeos::DBusThreadManager::Get()->GetDebugDaemonClient(); |
568 } | 562 } |
569 | 563 |
570 void TabManagerDelegate::LowMemoryKillImpl( | 564 void TabManagerDelegate::LowMemoryKillImpl( |
571 const TabStatsList& tab_list, | 565 const TabStatsList& tab_list, |
572 const std::vector<arc::ArcProcess>& arc_processes) { | 566 const std::vector<arc::ArcProcess>& arc_processes) { |
573 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 567 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
574 VLOG(2) << "LowMemoryKillImpl"; | 568 VLOG(2) << "LowMemoryKillImpl"; |
575 | 569 |
(...skipping 29 matching lines...) Expand all Loading... |
605 if (IsRecentlyKilledArcProcess(it->app()->process_name(), now)) { | 599 if (IsRecentlyKilledArcProcess(it->app()->process_name(), now)) { |
606 MEMORY_LOG(ERROR) << "Avoided killing " << it->app()->process_name() | 600 MEMORY_LOG(ERROR) << "Avoided killing " << it->app()->process_name() |
607 << " too often"; | 601 << " too often"; |
608 continue; | 602 continue; |
609 } | 603 } |
610 int estimated_memory_freed_kb = | 604 int estimated_memory_freed_kb = |
611 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); | 605 mem_stat_->EstimatedMemoryFreedKB(it->app()->pid()); |
612 if (KillArcProcess(it->app()->nspid())) { | 606 if (KillArcProcess(it->app()->nspid())) { |
613 recently_killed_arc_processes_[it->app()->process_name()] = now; | 607 recently_killed_arc_processes_[it->app()->process_name()] = now; |
614 target_memory_to_free_kb -= estimated_memory_freed_kb; | 608 target_memory_to_free_kb -= estimated_memory_freed_kb; |
615 MemoryKillsMonitor::LogLowMemoryKill("APP", estimated_memory_freed_kb); | 609 memory::MemoryKillsMonitor::LogLowMemoryKill("APP", |
| 610 estimated_memory_freed_kb); |
616 MEMORY_LOG(ERROR) << "Killed app " << it->app()->process_name() << " (" | 611 MEMORY_LOG(ERROR) << "Killed app " << it->app()->process_name() << " (" |
617 << it->app()->pid() << ")" | 612 << it->app()->pid() << ")" |
618 << ", estimated " << estimated_memory_freed_kb | 613 << ", estimated " << estimated_memory_freed_kb |
619 << " KB freed"; | 614 << " KB freed"; |
620 } else { | 615 } else { |
621 MEMORY_LOG(ERROR) << "Failed to kill " << it->app()->process_name(); | 616 MEMORY_LOG(ERROR) << "Failed to kill " << it->app()->process_name(); |
622 } | 617 } |
623 } else { | 618 } else { |
624 int64_t tab_id = it->tab()->tab_contents_id; | 619 int64_t tab_id = it->tab()->tab_contents_id; |
625 // The estimation is problematic since multiple tabs may share the same | 620 // The estimation is problematic since multiple tabs may share the same |
626 // process, while the calculation counts memory used by the whole process. | 621 // process, while the calculation counts memory used by the whole process. |
627 // So |estimated_memory_freed_kb| is an over-estimation. | 622 // So |estimated_memory_freed_kb| is an over-estimation. |
628 int estimated_memory_freed_kb = | 623 int estimated_memory_freed_kb = |
629 mem_stat_->EstimatedMemoryFreedKB(it->tab()->renderer_handle); | 624 mem_stat_->EstimatedMemoryFreedKB(it->tab()->renderer_handle); |
630 if (KillTab(tab_id)) { | 625 if (KillTab(tab_id)) { |
631 target_memory_to_free_kb -= estimated_memory_freed_kb; | 626 target_memory_to_free_kb -= estimated_memory_freed_kb; |
632 MemoryKillsMonitor::LogLowMemoryKill("TAB", estimated_memory_freed_kb); | 627 memory::MemoryKillsMonitor::LogLowMemoryKill("TAB", |
| 628 estimated_memory_freed_kb); |
633 MEMORY_LOG(ERROR) << "Killed tab " << it->tab()->title << " (" | 629 MEMORY_LOG(ERROR) << "Killed tab " << it->tab()->title << " (" |
634 << it->tab()->renderer_handle << "), estimated " | 630 << it->tab()->renderer_handle << "), estimated " |
635 << estimated_memory_freed_kb << " KB freed"; | 631 << estimated_memory_freed_kb << " KB freed"; |
636 } | 632 } |
637 } | 633 } |
638 } | 634 } |
639 if (target_memory_to_free_kb > 0) { | 635 if (target_memory_to_free_kb > 0) { |
640 MEMORY_LOG(ERROR) | 636 MEMORY_LOG(ERROR) |
641 << "Unable to kill enough candidates to meet target_memory_to_free_kb "; | 637 << "Unable to kill enough candidates to meet target_memory_to_free_kb "; |
642 } | 638 } |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
761 // Need to update OOM score if the calculated score is different from | 757 // Need to update OOM score if the calculated score is different from |
762 // current cached score. | 758 // current cached score. |
763 if (oom_score_map_[pid] != score) { | 759 if (oom_score_map_[pid] != score) { |
764 VLOG(3) << "Update OOM score " << score << " for " << *cur; | 760 VLOG(3) << "Update OOM score " << score << " for " << *cur; |
765 oom_scores_to_change[pid] = static_cast<int32_t>(score); | 761 oom_scores_to_change[pid] = static_cast<int32_t>(score); |
766 } | 762 } |
767 priority += priority_increment; | 763 priority += priority_increment; |
768 } | 764 } |
769 | 765 |
770 if (oom_scores_to_change.size()) { | 766 if (oom_scores_to_change.size()) { |
771 GetDebugDaemonClient()->SetOomScoreAdj( | 767 GetDebugDaemonClient()->SetOomScoreAdj(oom_scores_to_change, |
772 oom_scores_to_change, base::Bind(&OnSetOomScoreAdj)); | 768 base::Bind(&OnSetOomScoreAdj)); |
773 } | 769 } |
774 } | 770 } |
775 | 771 |
776 } // namespace memory | 772 } // namespace resource_coordinator |
OLD | NEW |