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
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/performance_manager/performance_manager_impl.h"
#include <atomic>
#include <memory>
#include <utility>
#include "base/check_op.h"
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/task/delayed_task_handle.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/time/time.h"
#include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/page_node_impl.h"
#include "components/performance_manager/graph/process_node_impl.h"
#include "components/performance_manager/graph/system_node_impl.h"
#include "components/performance_manager/graph/worker_node_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
#include "url/origin.h"
namespace performance_manager {
namespace {
// Singleton instance of PerformanceManagerImpl. Set from the constructor, and
// reset from the destructor. Null if the singleton instance doesn't exist,
// which only happens very early or very late in the process lifetime (or in
// some tests).
PerformanceManagerImpl* g_performance_manager = nullptr;
// Removes a frame tree from the graph starting from the leaf nodes.
void RemoveFrameAndChildrenFromGraph(FrameNodeImpl* frame_node,
GraphImpl* graph) {
// Recurse on the first child while there is one.
while (!frame_node->child_frame_nodes().empty()) {
RemoveFrameAndChildrenFromGraph(*(frame_node->child_frame_nodes().begin()),
graph);
}
// Now that all children are deleted, delete this frame.
graph->RemoveNode(frame_node);
}
} // namespace
// static
bool PerformanceManager::IsAvailable() {
return g_performance_manager;
}
PerformanceManagerImpl::~PerformanceManagerImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK_EQ(g_performance_manager, this);
// TODO(crbug.com/40629049): Move this to a TearDown function.
graph_.TearDown();
g_performance_manager = nullptr;
}
// static
GraphImpl* PerformanceManagerImpl::GetGraphImpl() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
CHECK(g_performance_manager);
return &g_performance_manager->graph_;
}
// static
std::unique_ptr<PerformanceManagerImpl> PerformanceManagerImpl::Create() {
return base::WrapUnique(new PerformanceManagerImpl());
}
// static
void PerformanceManagerImpl::Destroy(
std::unique_ptr<PerformanceManager> instance) {
// `instance` is deleted at the end of this function.
}
// static
std::unique_ptr<FrameNodeImpl> PerformanceManagerImpl::CreateFrameNode(
ProcessNodeImpl* process_node,
PageNodeImpl* page_node,
FrameNodeImpl* parent_frame_node,
FrameNodeImpl* outer_document_for_fenced_frame,
int render_frame_id,
const blink::LocalFrameToken& frame_token,
content::BrowsingInstanceId browsing_instance_id,
content::SiteInstanceGroupId site_instance_group_id,
bool is_current) {
return CreateNodeImpl<FrameNodeImpl>(
process_node, page_node, parent_frame_node,
outer_document_for_fenced_frame, render_frame_id, frame_token,
browsing_instance_id, site_instance_group_id, is_current);
}
// static
std::unique_ptr<PageNodeImpl> PerformanceManagerImpl::CreatePageNode(
base::WeakPtr<content::WebContents> web_contents,
const std::string& browser_context_id,
const GURL& visible_url,
PagePropertyFlags initial_property_flags,
base::TimeTicks visibility_change_time) {
return CreateNodeImpl<PageNodeImpl>(
std::move(web_contents), browser_context_id, visible_url,
initial_property_flags, visibility_change_time);
}
// static
std::unique_ptr<ProcessNodeImpl> PerformanceManagerImpl::CreateProcessNode(
BrowserProcessNodeTag tag) {
return CreateNodeImpl<ProcessNodeImpl>(tag);
}
// static
std::unique_ptr<ProcessNodeImpl> PerformanceManagerImpl::CreateProcessNode(
RenderProcessHostProxy render_process_host_proxy,
base::TaskPriority priority) {
return CreateNodeImpl<ProcessNodeImpl>(std::move(render_process_host_proxy),
priority);
}
// static
std::unique_ptr<ProcessNodeImpl> PerformanceManagerImpl::CreateProcessNode(
content::ProcessType process_type,
BrowserChildProcessHostProxy browser_child_process_host_proxy) {
return CreateNodeImpl<ProcessNodeImpl>(
process_type, std::move(browser_child_process_host_proxy));
}
// static
std::unique_ptr<WorkerNodeImpl> PerformanceManagerImpl::CreateWorkerNode(
const std::string& browser_context_id,
WorkerNode::WorkerType worker_type,
ProcessNodeImpl* process_node,
const blink::WorkerToken& worker_token,
const url::Origin& origin) {
return CreateNodeImpl<WorkerNodeImpl>(browser_context_id, worker_type,
process_node, worker_token, origin);
}
// static
void PerformanceManagerImpl::DeleteNode(std::unique_ptr<NodeBase> node) {
CHECK(IsAvailable());
GetGraphImpl()->RemoveNode(node.get());
// The node is deleted at the end of this function.
}
// static
void PerformanceManagerImpl::BatchDeleteNodes(
std::vector<std::unique_ptr<NodeBase>> nodes) {
GraphImpl* graph = GetGraphImpl();
base::flat_set<ProcessNodeImpl*> process_nodes;
for (const auto& node : nodes) {
switch (node->GetNodeType()) {
case PageNodeImpl::Type(): {
auto* page_node = PageNodeImpl::FromNodeBase(node.get());
// Delete the main frame nodes until no more exist.
while (!page_node->main_frame_nodes().empty()) {
RemoveFrameAndChildrenFromGraph(
*(page_node->main_frame_nodes().begin()), graph);
}
graph->RemoveNode(page_node);
break;
}
case ProcessNodeImpl::Type(): {
// Keep track of the process nodes for removing once all frames nodes
// are removed.
auto* process_node = ProcessNodeImpl::FromNodeBase(node.get());
process_nodes.insert(process_node);
break;
}
case FrameNodeImpl::Type():
break;
case WorkerNodeImpl::Type(): {
auto* worker_node = WorkerNodeImpl::FromNodeBase(node.get());
graph->RemoveNode(worker_node);
break;
}
case SystemNodeImpl::Type(): {
NOTREACHED();
}
}
}
// Remove the process nodes from the graph.
for (auto* process_node : process_nodes)
graph->RemoveNode(process_node);
// When |nodes| goes out of scope, all nodes are deleted.
}
PerformanceManagerImpl::PerformanceManagerImpl() {
DETACH_FROM_SEQUENCE(sequence_checker_);
CHECK(!g_performance_manager);
g_performance_manager = this;
graph_.SetUp();
graph_.set_ukm_recorder(ukm::UkmRecorder::Get());
}
// static
template <typename NodeType, typename... Args>
std::unique_ptr<NodeType> PerformanceManagerImpl::CreateNodeImpl(
Args&&... constructor_args) {
std::unique_ptr<NodeType> new_node =
std::make_unique<NodeType>(std::forward<Args>(constructor_args)...);
PerformanceManagerImpl::GetGraphImpl()->AddNewNode(new_node.get());
return new_node;
}
} // namespace performance_manager
|