blob: dd25eeb6604b5c3fdcf5d4b4fb71525bcba64752 [file] [log] [blame]
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/performance_monitor/process_metrics_history.h"
#include <limits>
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process_metrics.h"
#include "content/public/common/process_type.h"
#if defined(OS_MACOSX)
#include "content/public/browser/browser_child_process_host.h"
#endif
namespace performance_monitor {
// If a process is consistently above this CPU utilization percentage over time,
// we consider it as high and may take action.
const float kHighCPUUtilizationThreshold = 90.0f;
ProcessMetricsHistory::ProcessMetricsHistory() = default;
ProcessMetricsHistory::~ProcessMetricsHistory() = default;
void ProcessMetricsHistory::Initialize(
const ProcessMetricsMetadata& process_data,
int initial_update_sequence) {
DCHECK_EQ(base::kNullProcessHandle, process_data_.handle);
process_data_ = process_data;
last_update_sequence_ = initial_update_sequence;
#if defined(OS_MACOSX)
process_metrics_ = base::ProcessMetrics::CreateProcessMetrics(
process_data_.handle,
content::BrowserChildProcessHost::GetPortProvider());
#else
process_metrics_ =
base::ProcessMetrics::CreateProcessMetrics(process_data_.handle);
#endif
}
void ProcessMetricsHistory::SampleMetrics() {
cpu_usage_ = process_metrics_->GetPlatformIndependentCPUUsage();
#if defined(OS_WIN)
disk_usage_ = process_metrics_->GetDiskUsageBytesPerSecond();
#endif
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
idle_wakeups_ = process_metrics_->GetIdleWakeupsPerSecond();
#endif
#if defined(OS_MACOSX)
package_idle_wakeups_ = process_metrics_->GetPackageIdleWakeupsPerSecond();
#endif
}
void ProcessMetricsHistory::RunPerformanceTriggers() {
// We scale up to the equivalent of 64 CPU cores fully loaded. More than this
// doesn't really matter, as we're already in a terrible place.
const int kHistogramMin = 1;
const int kHistogramMax = 6400;
const int kHistogramBucketCount = 50;
#if defined(OS_WIN)
const int kDiskUsageHistogramMin = 1;
const int kDiskUsageHistogramMax = 200 * 1024 * 1024; // 200 M/sec.
const int kDiskUsageHistogramBucketCount = 50;
#endif
// The histogram macros don't support variables as histogram names,
// hence the macro duplication for each process type.
switch (process_data_.process_type) {
case content::PROCESS_TYPE_BROWSER:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"PerformanceMonitor.AverageCPU.BrowserProcess", cpu_usage_,
kHistogramMin, kHistogramMax, kHistogramBucketCount);
// If CPU usage has consistently been above our threshold,
// we *may* have an issue.
if (cpu_usage_ > kHighCPUUtilizationThreshold) {
UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.BrowserProcess",
true);
}
#if defined(OS_WIN)
UMA_HISTOGRAM_CUSTOM_COUNTS(
"PerformanceMonitor.AverageDisk.BrowserProcess", disk_usage_,
kDiskUsageHistogramMin, kDiskUsageHistogramMax,
kDiskUsageHistogramBucketCount);
#endif
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
UMA_HISTOGRAM_COUNTS_10000(
"PerformanceMonitor.IdleWakeups.BrowserProcess", idle_wakeups_);
#endif
#if defined(OS_MACOSX)
UMA_HISTOGRAM_COUNTS_1000(
"PerformanceMonitor.PackageExitIdleWakeups.BrowserProcess",
package_idle_wakeups_);
#endif
break;
case content::PROCESS_TYPE_RENDERER:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"PerformanceMonitor.AverageCPU.RendererProcess", cpu_usage_,
kHistogramMin, kHistogramMax, kHistogramBucketCount);
if (cpu_usage_ > kHighCPUUtilizationThreshold) {
UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.RendererProcess",
true);
}
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
UMA_HISTOGRAM_COUNTS_10000(
"PerformanceMonitor.IdleWakeups.RendererProcess", idle_wakeups_);
#endif
#if defined(OS_MACOSX)
UMA_HISTOGRAM_COUNTS_1000(
"PerformanceMonitor.PackageExitIdleWakeups.RendererProcess",
package_idle_wakeups_);
#endif
break;
case content::PROCESS_TYPE_GPU:
UMA_HISTOGRAM_CUSTOM_COUNTS("PerformanceMonitor.AverageCPU.GPUProcess",
cpu_usage_, kHistogramMin, kHistogramMax,
kHistogramBucketCount);
if (cpu_usage_ > kHighCPUUtilizationThreshold)
UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.GPUProcess", true);
#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_AIX)
UMA_HISTOGRAM_COUNTS_10000("PerformanceMonitor.IdleWakeups.GPUProcess",
idle_wakeups_);
#endif
#if defined(OS_MACOSX)
UMA_HISTOGRAM_COUNTS_1000(
"PerformanceMonitor.PackageExitIdleWakeups.GPUProcess",
package_idle_wakeups_);
#endif
break;
case content::PROCESS_TYPE_PPAPI_PLUGIN:
UMA_HISTOGRAM_CUSTOM_COUNTS("PerformanceMonitor.AverageCPU.PPAPIProcess",
cpu_usage_, kHistogramMin, kHistogramMax,
kHistogramBucketCount);
if (cpu_usage_ > kHighCPUUtilizationThreshold)
UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.PPAPIProcess", true);
break;
default:
break;
}
switch (process_data_.process_subtype) {
case kProcessSubtypeUnknown:
break;
case kProcessSubtypePPAPIFlash:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"PerformanceMonitor.AverageCPU.PPAPIFlashProcess", cpu_usage_,
kHistogramMin, kHistogramMax, kHistogramBucketCount);
if (cpu_usage_ > kHighCPUUtilizationThreshold) {
UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.PPAPIFlashProcess",
true);
}
break;
case kProcessSubtypeExtensionPersistent:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"PerformanceMonitor.AverageCPU.RendererExtensionPersistentProcess",
cpu_usage_, kHistogramMin, kHistogramMax, kHistogramBucketCount);
if (cpu_usage_ > kHighCPUUtilizationThreshold) {
UMA_HISTOGRAM_BOOLEAN(
"PerformanceMonitor.HighCPU.RendererExtensionPersistentProcess",
true);
}
break;
case kProcessSubtypeExtensionEvent:
UMA_HISTOGRAM_CUSTOM_COUNTS(
"PerformanceMonitor.AverageCPU.RendererExtensionEventProcess",
cpu_usage_, kHistogramMin, kHistogramMax, kHistogramBucketCount);
if (cpu_usage_ > kHighCPUUtilizationThreshold) {
UMA_HISTOGRAM_BOOLEAN(
"PerformanceMonitor.HighCPU.RendererExtensionEventProcess", true);
}
break;
}
}
} // namespace performance_monitor