| OLD | NEW |
| 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/chromeos/memory/oom_priority_manager.h" | 5 #include "chrome/browser/chromeos/memory/oom_priority_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 50 using content::BrowserThread; | 50 using content::BrowserThread; |
| 51 using content::WebContents; | 51 using content::WebContents; |
| 52 | 52 |
| 53 namespace chromeos { | 53 namespace chromeos { |
| 54 | 54 |
| 55 namespace { | 55 namespace { |
| 56 | 56 |
| 57 // Name of the experiment to run. | 57 // Name of the experiment to run. |
| 58 const char kExperiment[] = "LowMemoryMargin"; | 58 const char kExperiment[] = "LowMemoryMargin"; |
| 59 | 59 |
| 60 #define EXPERIMENT_CUSTOM_COUNTS(name, sample, min, max, buckets) \ | |
| 61 { \ | |
| 62 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, min, max, buckets); \ | |
| 63 if (base::FieldTrialList::TrialExists(kExperiment)) \ | |
| 64 UMA_HISTOGRAM_CUSTOM_COUNTS( \ | |
| 65 base::FieldTrial::MakeName(name, kExperiment), \ | |
| 66 sample, min, max, buckets); \ | |
| 67 } | |
| 68 | |
| 69 // Record a size in megabytes, over a potential interval up to 32 GB. | 60 // Record a size in megabytes, over a potential interval up to 32 GB. |
| 70 #define EXPERIMENT_HISTOGRAM_MEGABYTES(name, sample) \ | 61 #define HISTOGRAM_MEGABYTES(name, sample) \ |
| 71 EXPERIMENT_CUSTOM_COUNTS(name, sample, 1, 32768, 50) | 62 UMA_HISTOGRAM_CUSTOM_COUNTS(name, sample, 1, 32768, 50) |
| 72 | 63 |
| 73 // The default interval in seconds after which to adjust the oom_score_adj | 64 // The default interval in seconds after which to adjust the oom_score_adj |
| 74 // value. | 65 // value. |
| 75 const int kAdjustmentIntervalSeconds = 10; | 66 const int kAdjustmentIntervalSeconds = 10; |
| 76 | 67 |
| 77 // For each period of this length we record a statistic to indicate whether | 68 // For each period of this length we record a statistic to indicate whether |
| 78 // or not the user experienced a low memory event. If you change this interval | 69 // or not the user experienced a low memory event. If you change this interval |
| 79 // you must replace Tabs.Discard.DiscardInLastMinute with a new statistic. | 70 // you must replace Tabs.Discard.DiscardInLastMinute with a new statistic. |
| 80 const int kRecentTabDiscardIntervalSeconds = 60; | 71 const int kRecentTabDiscardIntervalSeconds = 60; |
| 81 | 72 |
| (...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 Browser* browser = *it; | 295 Browser* browser = *it; |
| 305 TabStripModel* model = browser->tab_strip_model(); | 296 TabStripModel* model = browser->tab_strip_model(); |
| 306 for (int idx = 0; idx < model->count(); idx++) { | 297 for (int idx = 0; idx < model->count(); idx++) { |
| 307 // Can't discard tabs that are already discarded or active. | 298 // Can't discard tabs that are already discarded or active. |
| 308 if (model->IsTabDiscarded(idx) || (model->active_index() == idx)) | 299 if (model->IsTabDiscarded(idx) || (model->active_index() == idx)) |
| 309 continue; | 300 continue; |
| 310 WebContents* web_contents = model->GetWebContentsAt(idx); | 301 WebContents* web_contents = model->GetWebContentsAt(idx); |
| 311 int64 web_contents_id = IdFromWebContents(web_contents); | 302 int64 web_contents_id = IdFromWebContents(web_contents); |
| 312 if (web_contents_id == target_web_contents_id) { | 303 if (web_contents_id == target_web_contents_id) { |
| 313 LOG(WARNING) << "Discarding tab " << idx | 304 LOG(WARNING) << "Discarding tab " << idx |
| 314 << " id " << target_web_contents_id; | 305 << " id " << target_web_contents_id; |
| 315 // Record statistics before discarding because we want to capture the | 306 // Record statistics before discarding because we want to capture the |
| 316 // memory state that lead to the discard. | 307 // memory state that lead to the discard. |
| 317 RecordDiscardStatistics(); | 308 RecordDiscardStatistics(); |
| 318 model->DiscardWebContentsAt(idx); | 309 model->DiscardWebContentsAt(idx); |
| 319 recent_tab_discard_ = true; | 310 recent_tab_discard_ = true; |
| 320 return true; | 311 return true; |
| 321 } | 312 } |
| 322 } | 313 } |
| 323 } | 314 } |
| 324 return false; | 315 return false; |
| 325 } | 316 } |
| 326 | 317 |
| 327 void OomPriorityManager::RecordDiscardStatistics() { | 318 void OomPriorityManager::RecordDiscardStatistics() { |
| 328 // Record a raw count so we can compare to discard reloads. | 319 // Record a raw count so we can compare to discard reloads. |
| 329 discard_count_++; | 320 discard_count_++; |
| 330 EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.DiscardCount", | 321 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 331 discard_count_, 1, 1000, 50); | 322 "Tabs.Discard.DiscardCount", discard_count_, 1, 1000, 50); |
| 332 | 323 |
| 333 // TODO(jamescook): Maybe incorporate extension count? | 324 // TODO(jamescook): Maybe incorporate extension count? |
| 334 EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.TabCount", GetTabCount(), 1, 100, 50); | 325 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 326 "Tabs.Discard.TabCount", GetTabCount(), 1, 100, 50); |
| 335 | 327 |
| 336 // TODO(jamescook): If the time stats prove too noisy, then divide up users | 328 // TODO(jamescook): If the time stats prove too noisy, then divide up users |
| 337 // based on how heavily they use Chrome using tab count as a proxy. | 329 // based on how heavily they use Chrome using tab count as a proxy. |
| 338 // Bin into <= 1, <= 2, <= 4, <= 8, etc. | 330 // Bin into <= 1, <= 2, <= 4, <= 8, etc. |
| 339 if (last_discard_time_.is_null()) { | 331 if (last_discard_time_.is_null()) { |
| 340 // This is the first discard this session. | 332 // This is the first discard this session. |
| 341 TimeDelta interval = TimeTicks::Now() - start_time_; | 333 TimeDelta interval = TimeTicks::Now() - start_time_; |
| 342 int interval_seconds = static_cast<int>(interval.InSeconds()); | 334 int interval_seconds = static_cast<int>(interval.InSeconds()); |
| 343 // Record time in seconds over an interval of approximately 1 day. | 335 // Record time in seconds over an interval of approximately 1 day. |
| 344 EXPERIMENT_CUSTOM_COUNTS( | 336 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 345 "Tabs.Discard.InitialTime2", interval_seconds, 1, 100000, 50); | 337 "Tabs.Discard.InitialTime2", interval_seconds, 1, 100000, 50); |
| 346 } else { | 338 } else { |
| 347 // Not the first discard, so compute time since last discard. | 339 // Not the first discard, so compute time since last discard. |
| 348 TimeDelta interval = TimeTicks::Now() - last_discard_time_; | 340 TimeDelta interval = TimeTicks::Now() - last_discard_time_; |
| 349 int interval_ms = static_cast<int>(interval.InMilliseconds()); | 341 int interval_ms = static_cast<int>(interval.InMilliseconds()); |
| 350 // Record time in milliseconds over an interval of approximately 1 day. | 342 // Record time in milliseconds over an interval of approximately 1 day. |
| 351 // Start at 100 ms to get extra resolution in the target 750 ms range. | 343 // Start at 100 ms to get extra resolution in the target 750 ms range. |
| 352 EXPERIMENT_CUSTOM_COUNTS( | 344 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 353 "Tabs.Discard.IntervalTime2", interval_ms, 100, 100000 * 1000, 50); | 345 "Tabs.Discard.IntervalTime2", interval_ms, 100, 100000 * 1000, 50); |
| 354 } | 346 } |
| 355 // Record Chrome's concept of system memory usage at the time of the discard. | 347 // Record Chrome's concept of system memory usage at the time of the discard. |
| 356 base::SystemMemoryInfoKB memory; | 348 base::SystemMemoryInfoKB memory; |
| 357 if (base::GetSystemMemoryInfo(&memory)) { | 349 if (base::GetSystemMemoryInfo(&memory)) { |
| 358 // TODO(jamescook): Remove this after R25 is deployed to stable. It does | 350 // TODO(jamescook): Remove this after R25 is deployed to stable. It does |
| 359 // not have sufficient resolution in the 2-4 GB range and does not properly | 351 // not have sufficient resolution in the 2-4 GB range and does not properly |
| 360 // account for graphics memory on ARM. Replace with MemAllocatedMB below. | 352 // account for graphics memory on ARM. Replace with MemAllocatedMB below. |
| 361 int mem_anonymous_mb = (memory.active_anon + memory.inactive_anon) / 1024; | 353 int mem_anonymous_mb = (memory.active_anon + memory.inactive_anon) / 1024; |
| 362 EXPERIMENT_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAnonymousMB", | 354 HISTOGRAM_MEGABYTES("Tabs.Discard.MemAnonymousMB", mem_anonymous_mb); |
| 363 mem_anonymous_mb); | |
| 364 | 355 |
| 365 // Record graphics GEM object size in a histogram with 50 MB buckets. | 356 // Record graphics GEM object size in a histogram with 50 MB buckets. |
| 366 int mem_graphics_gem_mb = 0; | 357 int mem_graphics_gem_mb = 0; |
| 367 if (memory.gem_size != -1) | 358 if (memory.gem_size != -1) |
| 368 mem_graphics_gem_mb = memory.gem_size / 1024 / 1024; | 359 mem_graphics_gem_mb = memory.gem_size / 1024 / 1024; |
| 369 RecordLinearHistogram( | 360 RecordLinearHistogram( |
| 370 "Tabs.Discard.MemGraphicsMB", mem_graphics_gem_mb, 2500, 50); | 361 "Tabs.Discard.MemGraphicsMB", mem_graphics_gem_mb, 2500, 50); |
| 371 | 362 |
| 372 // Record shared memory (used by renderer/GPU buffers). | 363 // Record shared memory (used by renderer/GPU buffers). |
| 373 int mem_shmem_mb = memory.shmem / 1024; | 364 int mem_shmem_mb = memory.shmem / 1024; |
| 374 RecordLinearHistogram("Tabs.Discard.MemShmemMB", mem_shmem_mb, 2500, 50); | 365 RecordLinearHistogram("Tabs.Discard.MemShmemMB", mem_shmem_mb, 2500, 50); |
| 375 | 366 |
| 376 // On Intel, graphics objects are in anonymous pages, but on ARM they are | 367 // On Intel, graphics objects are in anonymous pages, but on ARM they are |
| 377 // not. For a total "allocated count" add in graphics pages on ARM. | 368 // not. For a total "allocated count" add in graphics pages on ARM. |
| 378 int mem_allocated_mb = mem_anonymous_mb; | 369 int mem_allocated_mb = mem_anonymous_mb; |
| 379 #if defined(ARCH_CPU_ARM_FAMILY) | 370 #if defined(ARCH_CPU_ARM_FAMILY) |
| 380 mem_allocated_mb += mem_graphics_gem_mb; | 371 mem_allocated_mb += mem_graphics_gem_mb; |
| 381 #endif | 372 #endif |
| 382 EXPERIMENT_CUSTOM_COUNTS("Tabs.Discard.MemAllocatedMB", mem_allocated_mb, | 373 UMA_HISTOGRAM_CUSTOM_COUNTS( |
| 383 256, 32768, 50) | 374 "Tabs.Discard.MemAllocatedMB", mem_allocated_mb, 256, 32768, 50); |
| 384 | 375 |
| 385 int mem_available_mb = | 376 int mem_available_mb = |
| 386 (memory.active_file + memory.inactive_file + memory.free) / 1024; | 377 (memory.active_file + memory.inactive_file + memory.free) / 1024; |
| 387 EXPERIMENT_HISTOGRAM_MEGABYTES("Tabs.Discard.MemAvailableMB", | 378 HISTOGRAM_MEGABYTES("Tabs.Discard.MemAvailableMB", mem_available_mb); |
| 388 mem_available_mb); | |
| 389 } | 379 } |
| 390 // Set up to record the next interval. | 380 // Set up to record the next interval. |
| 391 last_discard_time_ = TimeTicks::Now(); | 381 last_discard_time_ = TimeTicks::Now(); |
| 392 } | 382 } |
| 393 | 383 |
| 394 void OomPriorityManager::RecordRecentTabDiscard() { | 384 void OomPriorityManager::RecordRecentTabDiscard() { |
| 395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 385 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 396 // If we change the interval we need to change the histogram name. | 386 // If we change the interval we need to change the histogram name. |
| 397 UMA_HISTOGRAM_BOOLEAN("Tabs.Discard.DiscardInLastMinute", | 387 UMA_HISTOGRAM_BOOLEAN("Tabs.Discard.DiscardInLastMinute", |
| 398 recent_tab_discard_); | 388 recent_tab_discard_); |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 642 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore( | 632 content::ZygoteHost::GetInstance()->AdjustRendererOOMScore( |
| 643 iterator->renderer_handle, score); | 633 iterator->renderer_handle, score); |
| 644 pid_to_oom_score_[iterator->renderer_handle] = score; | 634 pid_to_oom_score_[iterator->renderer_handle] = score; |
| 645 } | 635 } |
| 646 priority += priority_increment; | 636 priority += priority_increment; |
| 647 } | 637 } |
| 648 } | 638 } |
| 649 } | 639 } |
| 650 | 640 |
| 651 } // namespace chromeos | 641 } // namespace chromeos |
| OLD | NEW |