blob: 5e5478f60d1ac91093207912560ac54e3444b82f [file] [log] [blame]
// Copyright 2017 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 <map>
#include <memory>
#include <utility>
#include "base/macros.h"
#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/process/process_metrics.h"
#include "base/timer/timer.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "services/resource_coordinator/public/cpp/system_resource_coordinator.h"
namespace resource_coordinator {
// |RenderProcessProbe| collects measurements about render
// processes and propagates them to the |resource_coordinator| service.
// Currently this is only supported for Chrome Metrics experiments.
// The measurements are initiated from the UI thread, while acquiring and
// dispatching the measurements is done on the IO thread.
// This interface is broken out for testing.
class RenderProcessProbe {
// Returns the current |RenderProcessProbe| instance
// if one exists; otherwise it constructs a new instance.
static RenderProcessProbe* GetInstance();
static bool IsEnabled();
virtual ~RenderProcessProbe() = default;
// Starts a single collection cycle if a cycle is not already in progress.
// If a cycle is already in progress, this method will simply return.
virtual void StartSingleGather() = 0;
class RenderProcessProbeImpl : public RenderProcessProbe {
void StartSingleGather() override;
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class MeasurementOutcome {
kMeasurementSuccess = 0,
kMeasurementPartialSuccess = 1,
kMeasurementFailure = 2,
kMaxValue = kMeasurementFailure,
static constexpr base::TimeDelta kUninitializedCPUTime =
// Internal state protected for testing.
struct RenderProcessInfo {
base::Process process;
base::TimeDelta cpu_usage = kUninitializedCPUTime;
size_t last_gather_cycle_active = -1;
std::unique_ptr<base::ProcessMetrics> metrics;
using RenderProcessInfoMap = std::map<int, RenderProcessInfo>;
friend class base::NoDestructor<RenderProcessProbeImpl>;
~RenderProcessProbeImpl() override;
// (1) Identify all of the render processes that are active to measure.
// Child render processes can only be discovered in the browser's UI thread.
void RegisterAliveRenderProcessesOnUIThread();
// (2) Collect the render process CPU metrics and initiate a memory dump.
void CollectRenderProcessMetricsAndStartMemoryDumpOnIOThread();
// (3) Process the results of the memory dump and dispatch the results.
void ProcessGlobalMemoryDumpAndDispatchOnIOThread(
base::TimeTicks collection_start_time,
bool success,
std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump);
// (4) Finish the collection cycle on the UI thread.
void FinishCollectionOnUIThread(
mojom::ProcessResourceMeasurementBatchPtr batch);
// Test seams.
virtual void RegisterRenderProcesses();
virtual void StartMemoryMeasurement(base::TimeTicks collection_start_time);
virtual base::ProcessId GetProcessId(int host_id,
const RenderProcessInfo& info);
SystemResourceCoordinator* EnsureSystemResourceCoordinator();
// Dispatch the collected metrics.
// Virtual for testing.
virtual void DispatchMetricsOnUIThread(
mojom::ProcessResourceMeasurementBatchPtr batch);
// A map of currently running render process host IDs to process.
// This map is accessed alternatively from the UI thread and the IO thread,
// but only one of the two at a time.
RenderProcessInfoMap render_process_info_map_;
// Number of measurements collected so far.
size_t current_gather_cycle_ = 0u;
// True while a gathering cycle is underways on a background thread.
bool is_gathering_ = false;
// Used to signal the end of a CPU measurement cycle to the RC.
std::unique_ptr<SystemResourceCoordinator> system_resource_coordinator_;
} // namespace resource_coordinator