1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
|
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROCESS_NODE_IMPL_H_
#define COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROCESS_NODE_IMPL_H_
#include <optional>
#include <string>
#include <variant>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/time/time.h"
#include "base/types/pass_key.h"
#include "components/performance_manager/decorators/process_priority_aggregator_data.h"
#include "components/performance_manager/freezing/frozen_data.h"
#include "components/performance_manager/graph/node_attached_data_storage.h"
#include "components/performance_manager/graph/node_base.h"
#include "components/performance_manager/graph/node_inline_data.h"
#include "components/performance_manager/graph/properties.h"
#include "components/performance_manager/public/browser_child_process_host_proxy.h"
#include "components/performance_manager/public/graph/process_node.h"
#include "components/performance_manager/public/mojom/coordination_unit.mojom.h"
#include "components/performance_manager/public/mojom/v8_contexts.mojom.h"
#include "components/performance_manager/public/render_process_host_proxy.h"
#include "components/performance_manager/resource_attribution/cpu_measurement_data.h"
#include "components/performance_manager/scenarios/loading_scenario_data.h"
#include "components/performance_manager/scenarios/performance_scenario_data.h"
#include "content/public/browser/background_tracing_manager.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"
namespace performance_manager {
class FrameNodeImpl;
class FrozenFrameAggregator;
class ProcessNodeImpl;
class WorkerNodeImpl;
// Tag used to create a process node for the browser process.
struct BrowserProcessNodeTag {};
// A process node follows the lifetime of a chrome process.
// It may reference zero or one processes at a time, but during its lifetime, it
// may reference more than one process. This can happen if the associated
// renderer crashes, and an associated frame is then reloaded or re-navigated.
// The state of the process node goes through:
// 1. Created, no PID.
// 2. Process started, have PID - in the case where the associated render
// process fails to start, this state may not occur.
// 3. Process died or failed to start, have exit status.
// 4. Back to 2.
class ProcessNodeImpl
: public PublicNodeImpl<ProcessNodeImpl, ProcessNode>,
public TypedNodeBase<ProcessNodeImpl, ProcessNode, ProcessNodeObserver>,
public mojom::ProcessCoordinationUnit,
public mojom::ChildProcessCoordinationUnit,
public SupportsNodeInlineData<
ProcessPriorityAggregatorData,
FrozenData,
PerformanceScenarioData,
resource_attribution::CPUMeasurementData,
resource_attribution::SharedCPUTimeResultData,
LoadingScenarioCounts,
// Keep this last to avoid merge conflicts.
NodeAttachedDataStorage> {
public:
using PassKey = base::PassKey<ProcessNodeImpl>;
using TypedNodeBase<ProcessNodeImpl, ProcessNode, ProcessNodeObserver>::
FromNode;
// Constructor for the browser process.
explicit ProcessNodeImpl(BrowserProcessNodeTag tag);
// Constructor for a renderer process.
ProcessNodeImpl(RenderProcessHostProxy proxy, base::TaskPriority priority);
// Constructor for a non-renderer child process.
ProcessNodeImpl(content::ProcessType process_type,
BrowserChildProcessHostProxy proxy);
ProcessNodeImpl(const ProcessNodeImpl&) = delete;
ProcessNodeImpl& operator=(const ProcessNodeImpl&) = delete;
~ProcessNodeImpl() override;
void BindRenderProcessCoordinationUnit(
mojo::PendingReceiver<mojom::ProcessCoordinationUnit> receiver);
void BindChildProcessCoordinationUnit(
mojo::PendingReceiver<mojom::ChildProcessCoordinationUnit> receiver);
// mojom::ProcessCoordinationUnit implementation:
void SetMainThreadTaskLoadIsLow(bool main_thread_task_load_is_low) override;
void OnV8ContextCreated(
mojom::V8ContextDescriptionPtr description,
mojom::IframeAttributionDataPtr iframe_attribution_data) override;
void OnV8ContextDetached(
const blink::V8ContextToken& v8_context_token) override;
void OnV8ContextDestroyed(
const blink::V8ContextToken& v8_context_token) override;
void OnRemoteIframeAttached(
const blink::LocalFrameToken& parent_frame_token,
const blink::RemoteFrameToken& remote_frame_token,
mojom::IframeAttributionDataPtr iframe_attribution_data) override;
void OnRemoteIframeDetached(
const blink::LocalFrameToken& parent_frame_token,
const blink::RemoteFrameToken& remote_frame_token) override;
// mojom::ChildProcessCoordinationUnit implementation:
void InitializeChildProcessCoordination(
uint64_t process_track_id,
InitializeChildProcessCoordinationCallback callback) override;
// Partial ProcessNode implementation:
content::ProcessType GetProcessType() const override;
base::ProcessId GetProcessId() const override;
const base::Process& GetProcess() const override;
resource_attribution::ProcessContext GetResourceContext() const override;
base::TimeTicks GetLaunchTime() const override;
std::optional<int32_t> GetExitStatus() const override;
const std::string& GetMetricsName() const override;
bool GetMainThreadTaskLoadIsLow() const override;
uint64_t GetPrivateFootprintKb() const override;
uint64_t GetResidentSetKb() const override;
uint64_t GetPrivateSwapKb() const override;
RenderProcessHostId GetRenderProcessHostId() const override;
const RenderProcessHostProxy& GetRenderProcessHostProxy() const override;
const BrowserChildProcessHostProxy& GetBrowserChildProcessHostProxy()
const override;
base::TaskPriority GetPriority() const override;
ContentTypes GetHostedContentTypes() const override;
// Private implementation properties.
NodeSetView<FrameNodeImpl*> frame_nodes() const;
NodeSetView<WorkerNodeImpl*> worker_nodes() const;
std::optional<perfetto::Track> tracing_track() const;
void SetProcessExitStatus(int32_t exit_status);
void SetProcessMetricsName(const std::string& metrics_name);
void SetProcess(base::Process process, base::TimeTicks launch_time);
void set_private_footprint_kb(uint64_t private_footprint_kb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
private_footprint_kb_ = private_footprint_kb;
}
void set_resident_set_kb(uint64_t resident_set_kb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
resident_set_kb_ = resident_set_kb;
}
void set_private_swap_kb(uint64_t private_swap_kb) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
private_swap_kb_ = private_swap_kb;
}
// Add |frame_node| to this process.
void AddFrame(FrameNodeImpl* frame_node);
// Removes |frame_node| from the set of frames hosted by this process. Invoked
// when the frame is removed from the graph.
void RemoveFrame(FrameNodeImpl* frame_node);
// Add |worker_node| to this process.
void AddWorker(WorkerNodeImpl* worker_node);
// Removes |worker_node| from the set of workers hosted by this process.
// Invoked when the worker is removed from the graph.
void RemoveWorker(WorkerNodeImpl* worker_node);
void set_priority(base::TaskPriority priority);
// Adds a new type of hosted content to the |hosted_content_types| bit field.
void add_hosted_content_type(ContentType content_type);
void OnAllFramesInProcessFrozen(base::PassKey<FrozenFrameAggregator>) {
OnAllFramesInProcessFrozen();
}
void OnAllFramesInProcessFrozenForTesting() { OnAllFramesInProcessFrozen(); }
base::WeakPtr<ProcessNodeImpl> GetWeakPtr();
static PassKey CreatePassKeyForTesting() { return PassKey(); }
protected:
void SetProcessImpl(base::Process process,
base::ProcessId process_id,
base::TimeTicks launch_time);
private:
friend class ProcessMetricsDecoratorAccess;
using AnyChildProcessHostProxy =
std::variant<RenderProcessHostProxy, BrowserChildProcessHostProxy>;
// Shared constructor for all process types.
ProcessNodeImpl(content::ProcessType process_type,
AnyChildProcessHostProxy proxy,
base::TaskPriority priority);
// Rest of ProcessNode implementation. These are private so that users of the
// impl use the private getters rather than the public interface.
NodeSetView<const FrameNode*> GetFrameNodes() const override;
NodeSetView<const WorkerNode*> GetWorkerNodes() const override;
void OnAllFramesInProcessFrozen();
// NodeBase:
void OnInitializingProperties() override;
void OnUninitializingEdges() override;
void CleanUpNodeState() override;
// Receiver for renderer-only messages.
mojo::Receiver<mojom::ProcessCoordinationUnit> render_process_receiver_
GUARDED_BY_CONTEXT(sequence_checker_){this};
// Receiver for messages from all child processes.
mojo::Receiver<mojom::ChildProcessCoordinationUnit> child_process_receiver_
GUARDED_BY_CONTEXT(sequence_checker_){this};
uint64_t private_footprint_kb_ GUARDED_BY_CONTEXT(sequence_checker_) = 0u;
uint64_t resident_set_kb_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
uint64_t private_swap_kb_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
base::ProcessId process_id_ GUARDED_BY_CONTEXT(sequence_checker_) =
base::kNullProcessId;
ObservedProperty::NotifiesAlways<
base::Process,
&ProcessNodeObserver::OnProcessLifetimeChange>
process_ GUARDED_BY_CONTEXT(sequence_checker_);
base::TimeTicks launch_time_ GUARDED_BY_CONTEXT(sequence_checker_);
std::optional<int32_t> exit_status_ GUARDED_BY_CONTEXT(sequence_checker_);
std::string metrics_name_ GUARDED_BY_CONTEXT(sequence_checker_);
// The type of the process that this node represents.
const content::ProcessType process_type_;
// The proxy that allows access to either the RenderProcessHost or the
// BrowserChildProcessHost associated with this process, if `this` is a
// process node for a child process (process_type() != PROCESS_TYPE_BROWSER).
const AnyChildProcessHostProxy child_process_host_proxy_;
ObservedProperty::NotifiesOnlyOnChanges<
bool,
&ProcessNodeObserver::OnMainThreadTaskLoadIsLow>
main_thread_task_load_is_low_ GUARDED_BY_CONTEXT(sequence_checker_){
false};
// Process priority information. This is aggregated from the priority of
// all workers and frames in a given process by the ProcessPriorityAggregator.
// Initially high priority until the first execution context it hosts
// determine the right priority.
ObservedProperty::NotifiesOnlyOnChangesWithPreviousValue<
base::TaskPriority,
base::TaskPriority,
&ProcessNodeObserver::OnPriorityChanged>
priority_ GUARDED_BY_CONTEXT(sequence_checker_);
// A bit field that indicates which type of content this process has hosted,
// either currently or in the past.
ContentTypes hosted_content_types_ GUARDED_BY_CONTEXT(sequence_checker_);
// The Perfetto ProcessTrack for this process.
std::optional<perfetto::Track> tracing_track_
GUARDED_BY_CONTEXT(sequence_checker_);
NodeSet frame_nodes_ GUARDED_BY_CONTEXT(sequence_checker_);
NodeSet worker_nodes_ GUARDED_BY_CONTEXT(sequence_checker_);
base::WeakPtrFactory<ProcessNodeImpl> weak_factory_
GUARDED_BY_CONTEXT(sequence_checker_){this};
};
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_GRAPH_PROCESS_NODE_IMPL_H_
|