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