process_metrics_history.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <limits> 6 7#include "base/logging.h" 8#include "base/metrics/histogram.h" 9#include "base/process/process_metrics.h" 10 11#include "chrome/browser/performance_monitor/process_metrics_history.h" 12#if defined(OS_MACOSX) 13#include "content/public/browser/browser_child_process_host.h" 14#endif 15#include "content/public/common/process_type.h" 16 17namespace performance_monitor { 18 19// If a process is consistently above this CPU utilization percentage over time, 20// we consider it as high and may take action. 21const float kHighCPUUtilizationThreshold = 90.0f; 22 23ProcessMetricsHistory::ProcessMetricsHistory() 24 : process_handle_(0), 25 process_type_(content::PROCESS_TYPE_UNKNOWN), 26 last_update_sequence_(0) { 27 ResetCounters(); 28} 29 30ProcessMetricsHistory::~ProcessMetricsHistory() {} 31 32void ProcessMetricsHistory::ResetCounters() { 33 min_cpu_usage_ = std::numeric_limits<double>::max(); 34 accumulated_cpu_usage_ = 0.0; 35 accumulated_private_bytes_ = 0; 36 accumulated_shared_bytes_ = 0; 37 sample_count_ = 0; 38} 39 40void ProcessMetricsHistory::Initialize(base::ProcessHandle process_handle, 41 int process_type, 42 int initial_update_sequence) { 43 DCHECK(process_handle_ == 0); 44 process_handle_ = process_handle; 45 process_type_ = process_type; 46 last_update_sequence_ = initial_update_sequence; 47 48#if defined(OS_MACOSX) 49 process_metrics_.reset(base::ProcessMetrics::CreateProcessMetrics( 50 process_handle_, content::BrowserChildProcessHost::GetPortProvider())); 51#else 52 process_metrics_.reset( 53 base::ProcessMetrics::CreateProcessMetrics(process_handle_)); 54#endif 55} 56 57void ProcessMetricsHistory::SampleMetrics() { 58 double cpu_usage = process_metrics_->GetPlatformIndependentCPUUsage(); 59 min_cpu_usage_ = std::min(min_cpu_usage_, cpu_usage); 60 accumulated_cpu_usage_ += cpu_usage; 61 62 size_t private_bytes = 0; 63 size_t shared_bytes = 0; 64 if (!process_metrics_->GetMemoryBytes(&private_bytes, &shared_bytes)) 65 LOG(WARNING) << "GetMemoryBytes returned NULL (platform-specific error)"; 66 67 accumulated_private_bytes_ += private_bytes; 68 accumulated_shared_bytes_ += shared_bytes; 69 70 sample_count_++; 71} 72 73void ProcessMetricsHistory::EndOfCycle() { 74 RunPerformanceTriggers(); 75 ResetCounters(); 76} 77 78void ProcessMetricsHistory::RunPerformanceTriggers() { 79 if (sample_count_ == 0) 80 return; 81 82 // We scale up to the equivalent of 64 CPU cores fully loaded. More than this 83 // doesn't really matter, as we're already in a terrible place. 84 const int kHistogramMin = 0; 85 const int kHistogramMax = 6400; 86 const int kHistogramBucketCount = 50; 87 88 const double average_cpu_usage = accumulated_cpu_usage_ / sample_count_; 89 90 // The histogram macros don't support variables as histogram names, 91 // hence the macro duplication for each process type. 92 switch (process_type_) { 93 case content::PROCESS_TYPE_BROWSER: 94 UMA_HISTOGRAM_CUSTOM_COUNTS( 95 "PerformanceMonitor.AverageCPU.BrowserProcess", average_cpu_usage, 96 kHistogramMin, kHistogramMax, kHistogramBucketCount); 97 // If CPU usage has consistently been above our threshold, 98 // we *may* have an issue. 99 if (min_cpu_usage_ > kHighCPUUtilizationThreshold) { 100 UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.BrowserProcess", 101 true); 102 } 103 break; 104 case content::PROCESS_TYPE_RENDERER: 105 UMA_HISTOGRAM_CUSTOM_COUNTS( 106 "PerformanceMonitor.AverageCPU.RendererProcess", average_cpu_usage, 107 kHistogramMin, kHistogramMax, kHistogramBucketCount); 108 if (min_cpu_usage_ > kHighCPUUtilizationThreshold) { 109 UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.RendererProcess", 110 true); 111 } 112 break; 113 case content::PROCESS_TYPE_PLUGIN: 114 UMA_HISTOGRAM_CUSTOM_COUNTS( 115 "PerformanceMonitor.AverageCPU.PluginProcess", average_cpu_usage, 116 kHistogramMin, kHistogramMax, kHistogramBucketCount); 117 if (min_cpu_usage_ > kHighCPUUtilizationThreshold) 118 UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.PluginProcess", true); 119 break; 120 case content::PROCESS_TYPE_GPU: 121 UMA_HISTOGRAM_CUSTOM_COUNTS( 122 "PerformanceMonitor.AverageCPU.GPUProcess", average_cpu_usage, 123 kHistogramMin, kHistogramMax, kHistogramBucketCount); 124 if (min_cpu_usage_ > kHighCPUUtilizationThreshold) 125 UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.GPUProcess", true); 126 break; 127 case content::PROCESS_TYPE_PPAPI_PLUGIN: 128 UMA_HISTOGRAM_CUSTOM_COUNTS( 129 "PerformanceMonitor.AverageCPU.PPAPIProcess", average_cpu_usage, 130 kHistogramMin, kHistogramMax, kHistogramBucketCount); 131 if (min_cpu_usage_ > kHighCPUUtilizationThreshold) 132 UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.PPAPIProcess", true); 133 break; 134 default: 135 break; 136 } 137} 138 139} // namespace performance_monitor 140