blob: ffa3b3be479651769c4bc9e246c9b5d2fbb72dfe [file] [log] [blame]
// Copyright (c) 2012 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.
#ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_PROCESS_MONITOR_H_
#define CHROME_BROWSER_PERFORMANCE_MONITOR_PROCESS_MONITOR_H_
#include <map>
#include <memory>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/process/process_handle.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "content/public/common/process_type.h"
#if defined(OS_MAC)
#include "chrome/browser/performance_monitor/resource_coalition_mac.h"
#endif
namespace performance_monitor {
class ProcessMetricsHistory;
enum ProcessSubtypes {
kProcessSubtypeUnknown,
kProcessSubtypeExtensionPersistent,
kProcessSubtypeExtensionEvent,
kProcessSubtypeNetworkProcess,
};
struct ProcessMetadata {
base::ProcessHandle handle = base::kNullProcessHandle;
int process_type = content::PROCESS_TYPE_UNKNOWN;
ProcessSubtypes process_subtype = kProcessSubtypeUnknown;
};
// ProcessMonitor is a tool which periodically monitors performance metrics
// of all the Chrome processes for histogram logging and possibly taking action
// upon noticing serious performance degradation.
class ProcessMonitor {
public:
// The interval at which ProcessMonitor performs its timed collections.
static constexpr base::TimeDelta kGatherInterval = base::Minutes(2);
struct Metrics {
Metrics();
Metrics(const Metrics& other);
Metrics& operator=(const Metrics& other);
~Metrics();
// The percentage of time spent executing, across all threads of the
// process, in the interval since the last time the metric was sampled. This
// can exceed 100% in multi-thread processes running on multi-core systems.
double cpu_usage = 0.0;
#if defined(OS_MAC) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
defined(OS_AIX)
// Returns the number of average idle cpu wakeups per second since the last
// time the metric was sampled.
int idle_wakeups = 0;
#endif
#if defined(OS_MAC)
// The number of average "package idle exits" per second since the last
// time the metric was sampled. See base/process/process_metrics.h for a
// more detailed explanation.
int package_idle_wakeups = 0;
// "Energy Impact" is a synthetic power estimation metric displayed by macOS
// in Activity Monitor and the battery menu.
double energy_impact = 0.0;
// Process coalition data. Only available for aggregated metrics (not
// individual processes), on some Mac devices. absl::nullopt if not
// available.
absl::optional<ResourceCoalition::DataRate> coalition_data;
#endif
};
class Observer : public base::CheckedObserver {
public:
// Provides the sampled metrics for every Chrome process. This is called
// once per process at a regular interval.
virtual void OnMetricsSampled(const ProcessMetadata& process_metadata,
const Metrics& metrics) {}
// Provides the aggregated sampled metrics from every Chrome process. This
// is called once at a regular interval regardless of the number of
// processes.
virtual void OnAggregatedMetricsSampled(const Metrics& metrics) {}
};
// Creates and returns the application-wide ProcessMonitor. Can only be called
// if no ProcessMonitor instances exists in the current process. The caller
// owns the created instance. The current process' instance can be retrieved
// with Get().
static std::unique_ptr<ProcessMonitor> Create();
// Returns the application-wide ProcessMonitor if one exists; otherwise
// returns nullptr.
static ProcessMonitor* Get();
ProcessMonitor(const ProcessMonitor&) = delete;
ProcessMonitor& operator=(const ProcessMonitor&) = delete;
virtual ~ProcessMonitor();
// Start the cycle of metrics gathering.
void StartGatherCycle();
// Adds/removes an observer.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
protected:
ProcessMonitor();
base::ObserverList<Observer>& GetObserversForTesting() {
return observer_list_;
}
private:
// Mark the given process as alive in the current update iteration.
// This means adding an entry to the map of watched processes if it's not
// already present.
void MarkProcessAsAlive(const ProcessMetadata& process_data,
int current_update_sequence);
// Returns the ProcessMetadata for renderer processes.
static std::vector<ProcessMetadata> GatherRendererProcesses();
// Returns the ProcessMetadata for non renderers.
static std::vector<ProcessMetadata> GatherNonRendererProcesses();
// Gather all the processes and updates the ProcessMetrics map with the
// current list of processes and gathers metrics from each entry.
void GatherProcesses();
// A map of currently running ProcessHandles to ProcessMetrics.
std::map<base::ProcessHandle, std::unique_ptr<ProcessMetricsHistory>>
metrics_map_;
// The timer to signal ProcessMonitor to perform its timed collections.
base::RepeatingTimer repeating_timer_;
base::ObserverList<Observer> observer_list_;
#if defined(OS_MAC)
ResourceCoalition coalition_data_provider_;
#endif
base::WeakPtrFactory<ProcessMonitor> weak_ptr_factory_{this};
};
} // namespace performance_monitor
#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_PROCESS_MONITOR_H_