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