| Index: chrome/browser/performance_monitor/performance_monitor.cc
|
| diff --git a/chrome/browser/performance_monitor/performance_monitor.cc b/chrome/browser/performance_monitor/performance_monitor.cc
|
| index 7e6122f45297ed4ec8fd34da2ebda48ea09d9b7a..83f275515b827e435d4d9e415dac8a02942503a0 100644
|
| --- a/chrome/browser/performance_monitor/performance_monitor.cc
|
| +++ b/chrome/browser/performance_monitor/performance_monitor.cc
|
| @@ -4,9 +4,18 @@
|
|
|
| #include "chrome/browser/performance_monitor/performance_monitor.h"
|
|
|
| +#include <algorithm>
|
| +#include <map>
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| #include "base/bind.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/linked_ptr.h"
|
| +#include "base/process.h"
|
| #include "base/process_util.h"
|
| +#include "base/stl_util.h"
|
| +#include "base/string_number_conversions.h"
|
| #include "base/threading/worker_pool.h"
|
| #include "base/time.h"
|
| #include "chrome/browser/browser_shutdown.h"
|
| @@ -18,6 +27,7 @@
|
| #include "chrome/common/chrome_version_info.h"
|
| #include "chrome/common/extensions/extension.h"
|
| #include "chrome/common/extensions/extension_constants.h"
|
| +#include "chrome/test/base/chrome_process_util.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/notification_service.h"
|
| #include "content/public/browser/notification_types.h"
|
| @@ -27,6 +37,22 @@
|
| using content::BrowserThread;
|
| using extensions::Extension;
|
|
|
| +namespace {
|
| +
|
| +template <class T>
|
| +T GetMedian(std::vector<T> vec) {
|
| + typedef typename std::vector<T>::size_type vec_size;
|
| +
|
| + vec_size size = vec.size();
|
| + DCHECK(size != 0);
|
| + std::sort(vec.begin(), vec.end());
|
| + vec_size mid = size / 2;
|
| +
|
| + return size % 2 == 0 ? (vec[mid] + vec[mid - 1]) / 2 : vec[mid];
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| namespace performance_monitor {
|
|
|
| PerformanceMonitor::PerformanceMonitor() : database_(NULL) {
|
| @@ -164,6 +190,101 @@ void PerformanceMonitor::NotifyInitialized() {
|
| content::NotificationService::NoDetails());
|
| }
|
|
|
| +void PerformanceMonitor::GatherStatisticsOnBackgroundThread() {
|
| + CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| +
|
| + // Because the CPU usage is gathered as an average since the last time the
|
| + // function was called, while the memory usage is gathered as an instantaneous
|
| + // usage, the CPU usage is gathered before the metrics map is wiped.
|
| + GatherCPUUsage();
|
| + UpdateMetricsMap();
|
| + GatherMemoryUsage();
|
| +}
|
| +
|
| +void PerformanceMonitor::GatherCPUUsage() {
|
| + std::vector<double> cpu_usage_vec;
|
| +
|
| + if (metrics_map_.size()) {
|
| + for (MetricsMap::const_iterator iter = metrics_map_.begin();
|
| + iter != metrics_map_.end(); ++iter)
|
| + cpu_usage_vec.push_back(iter->second->GetCPUUsage());
|
| +
|
| + std::sort(cpu_usage_vec.begin(), cpu_usage_vec.end());
|
| + database_->AddMetric(performance_monitor::kMetricCPUUsage,
|
| + base::DoubleToString(GetMedian(cpu_usage_vec)));
|
| + }
|
| +}
|
| +
|
| +void PerformanceMonitor::GatherMemoryUsage() {
|
| + std::vector<size_t> private_memory_vec;
|
| + std::vector<size_t> shared_memory_vec;
|
| +
|
| + size_t private_memory = 0;
|
| + size_t shared_memory = 0;
|
| + for (MetricsMap::const_iterator iter = metrics_map_.begin();
|
| + iter != metrics_map_.end(); ++iter) {
|
| + if (iter->second->GetMemoryBytes(&private_memory, &shared_memory)) {
|
| + private_memory_vec.push_back(private_memory);
|
| + shared_memory_vec.push_back(shared_memory);
|
| + } else {
|
| + LOG(ERROR) << "GetMemoryBytes returned NULL (platform-specific error)";
|
| + }
|
| + }
|
| +
|
| + if (!private_memory_vec.size())
|
| + return;
|
| +
|
| + std::sort(private_memory_vec.begin(), private_memory_vec.end());
|
| + std::sort(shared_memory_vec.begin(), shared_memory_vec.end());
|
| +
|
| + database_->AddMetric(performance_monitor::kMetricPrivateMemoryUsage,
|
| + base::Uint64ToString(GetMedian(private_memory_vec)));
|
| + database_->AddMetric(performance_monitor::kMetricSharedMemoryUsage,
|
| + base::Uint64ToString(GetMedian(shared_memory_vec)));
|
| +}
|
| +
|
| +void PerformanceMonitor::UpdateMetricsMap() {
|
| + // Remove old process handles. Use two iterators to safely call erase()
|
| + // on the current element, and advance by a call to iter = iter_next++.
|
| + // The third iterator saves us from calling end() every loop.
|
| + for (MetricsMap::iterator iter = metrics_map_.begin(), iter_next = iter,
|
| + iter_end = metrics_map_.end(); iter != iter_end; iter = iter_next;) {
|
| + ++iter_next;
|
| +
|
| + if (base::GetTerminationStatus(iter->first, NULL) !=
|
| + base::TERMINATION_STATUS_STILL_RUNNING) {
|
| + base::CloseProcessHandle(iter->first);
|
| + metrics_map_.erase(iter);
|
| + } else {
|
| + // Prime the CPUUsage to be gathered next time.
|
| + iter->second->GetCPUUsage();
|
| + }
|
| + }
|
| +
|
| + // Add new process handles.
|
| + base::ProcessId browser_pid = base::GetCurrentProcId();
|
| + ChromeProcessList chrome_processes(GetRunningChromeProcesses(browser_pid));
|
| + for (ChromeProcessList::const_iterator pid_iter = chrome_processes.begin();
|
| + pid_iter != chrome_processes.end(); ++pid_iter) {
|
| + base::ProcessHandle process_handle;
|
| + if (base::OpenProcessHandle(*pid_iter, &process_handle) &&
|
| + !ContainsKey(metrics_map_, process_handle)) {
|
| +#if !defined(OS_MACOSX)
|
| + linked_ptr<base::ProcessMetrics> process_metrics(
|
| + base::ProcessMetrics::CreateProcessMetrics(process_handle));
|
| +#else
|
| + linked_ptr<base::ProcessMetrics> process_metrics(
|
| + base::ProcessMetrics::CreateProcessMetrics(process_handle,
|
| + content::BrowserChildProcessHost::GetPortProvider()));
|
| +#endif
|
| + // Prime the CPUUsage to be gathered next time.
|
| + process_metrics->GetCPUUsage();
|
| +
|
| + metrics_map_[process_handle] = process_metrics;
|
| + }
|
| + }
|
| +}
|
| +
|
| void PerformanceMonitor::Observe(int type,
|
| const content::NotificationSource& source,
|
| const content::NotificationDetails& details) {
|
|
|