blob: 6594bc0225a63ecfea1102c44927681d89710e60 [file] [log] [blame]
// Copyright 2019 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_SYSTEM_MONITOR_H_
#define CHROME_BROWSER_PERFORMANCE_MONITOR_SYSTEM_MONITOR_H_
#include <memory>
#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/sequence_checker.h"
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
namespace performance_monitor {
class SystemMonitorHelper;
// Monitors various various system metrics such as free memory, disk idle time,
// etc.
//
// Must be created and used from the UI thread.
//
// Users of this class need to subscribe as observers via the
// AddOrUpdateObserver method. They need to specify which metrics they're
// interested in and at which frequency they should be refreshed. This set of
// metrics and frequencies can then be updated at runtime.
//
// Platforms that want to use this class need to provide a platform specific
// implementation of the SystemMonitorHelper class and update
// SystemMonitor::Create.
class SystemMonitor {
public:
// The frequency at which a metric will be collected. Exact frequencies are
// implementation details determined by experimentation.
//
// NOTE: Frequencies must be listed in increasing order in this enum.
enum class SamplingFrequency : uint32_t {
kNoSampling = 0,
kDefaultFrequency = 1,
};
virtual ~SystemMonitor();
// Creates and returns the application-wide SystemMonitor. Can only be called
// if no SystemMonitor instance exists in the current process. The caller
// owns the created instance. The current process' instance can be retrieved
// with Get().
static std::unique_ptr<SystemMonitor> Create();
// Get the application-wide SystemMonitor (if not present, returns
// nullptr).
static SystemMonitor* Get();
// Observer that should be notified when new samples are available.
//
// When being registered, an observer should declare the metrics it want to
// track and their refresh frequency.
class SystemObserver : public base::CheckedObserver {
public:
// A struct that associates metrics with their refresh frequencies.
struct MetricRefreshFrequencies {
SamplingFrequency free_phys_memory_mb_frequency =
SamplingFrequency::kNoSampling;
};
~SystemObserver() override = default;
// Reports the amount of free physical memory, in MB.
virtual void OnFreePhysicalMemoryMbSample(int free_phys_memory_mb);
};
using ObserverToFrequenciesMap =
base::flat_map<SystemObserver*, SystemObserver::MetricRefreshFrequencies>;
// Adds |observer| as an observer and updates the metrics to collect and their
// frequencies based on |metrics_frequencies|. If this observer is already
// in the list then this simply updates the list of metrics to collect or
// their frequency.
void AddOrUpdateObserver(
SystemObserver* observer,
SystemObserver::MetricRefreshFrequencies metrics_frequencies);
// Removes |observer| from the observer list. After this call, the observer
// will not receive notifications for any metric.
void RemoveObserver(SystemObserver* observer);
const SystemObserver::MetricRefreshFrequencies&
metric_refresh_frequencies_for_testing() const {
return metrics_refresh_frequencies_;
}
bool IsRefreshTimerRunningForTesting() { return refresh_timer_.IsRunning(); }
void SetHelperForTesting(std::unique_ptr<SystemMonitorHelper> helper) {
async_helper_.reset(helper.release());
}
protected:
friend class SystemMonitorHelper;
// Creates SystemMonitor. Only one SystemMonitor instance per
// application is allowed.
explicit SystemMonitor(std::unique_ptr<SystemMonitorHelper> helper);
// A struct that stores a refreshed metric and the reason why it has been
// refreshed.
template <typename T>
struct MetricAndRefreshReason {
MetricAndRefreshReason() {}
MetricAndRefreshReason(T value, SamplingFrequency reason)
: metric_value(value), refresh_reason(reason) {}
T metric_value = {};
SamplingFrequency refresh_reason = SamplingFrequency::kNoSampling;
};
// Struct that will receive the refreshed metrics in the refresh callback.
struct MetricsRefresh {
MetricsRefresh();
MetricsRefresh(MetricsRefresh&& o);
MetricAndRefreshReason<int> free_phys_memory_mb;
};
private:
// Updates |observed_metrics_| with the list of metrics that need to be
// tracked.
void UpdateObservedMetricsSet();
// Function that gets called by every time the refresh callback triggers.
void RefreshCallback();
// Notify the observers with the refreshed metrics.
void NotifyObservers(const MetricsRefresh& metrics);
// The list of observers.
base::ObserverList<SystemObserver> observers_;
// A map that associates an observer to the metrics it's interested in.
ObserverToFrequenciesMap observer_metrics_;
// The current metrics that are being observed and the corresponding refresh
// frequency.
SystemObserver::MetricRefreshFrequencies metrics_refresh_frequencies_;
// The timer responsible of refreshing the metrics and notifying the
// observers.
base::OneShotTimer refresh_timer_;
// The task runner used to run all the blocking operations.
const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
// The SystemMonitorHelper instance responsible for running all asynchronous
// operations.
std::unique_ptr<SystemMonitorHelper, base::OnTaskRunnerDeleter> async_helper_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<SystemMonitor> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(SystemMonitor);
};
// Helper class used to run all the blocking operations posted by SystemMonitor
// on a sequence with the |MayBlock()| trait.
//
// Instances of this class should only be destructed once all the posted tasks
// have been run, in practice it means that they should ideally be stored in a
// std::unique_ptr<AsyncHelper, base::OnTaskRunnerDeleter>.
class SystemMonitorHelper {
public:
using MetricsRefresh = SystemMonitor::MetricsRefresh;
template <typename T>
using MetricAndRefreshReason = SystemMonitor::MetricAndRefreshReason<T>;
SystemMonitorHelper() = default;
virtual ~SystemMonitorHelper() = default;
// Returns the refresh interval that should be used by the SystemMonitor
// refresh timer based on the current configuration of its observers. If no
// metrics are being observed then this returns base::TimeDelta::Max().
//
// This can be called from any sequence.
virtual base::TimeDelta GetRefreshInterval(
const SystemMonitor::SystemObserver::MetricRefreshFrequencies&
metrics_and_frequencies) = 0;
// Refresh the metrics according to |metrics_and_frequencies|. |refresh_time|
// indicates at which time the refresh has been requested.
virtual MetricsRefresh RefreshMetrics(
const SystemMonitor::SystemObserver::MetricRefreshFrequencies
metrics_and_frequencies,
const base::TimeTicks& refresh_time) = 0;
private:
DISALLOW_COPY_AND_ASSIGN(SystemMonitorHelper);
};
} // namespace performance_monitor
#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_SYSTEM_MONITOR_H_