Commit fab8e9eb authored by Sigurdur Asgeirsson's avatar Sigurdur Asgeirsson Committed by Commit Bot

[PM] Implement NodeDataDescriber and its registry.

BUG: 1068233

Change-Id: I097c23f8e490dfe37fdffe54f83be7b28f52205c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2135947
Commit-Queue: Sigurður Ásgeirsson <siggi@chromium.org>
Reviewed-by: default avatarJoe Mason <joenotcharles@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757186}
parent 7d0118d8
...@@ -30,6 +30,7 @@ static_library("performance_manager") { ...@@ -30,6 +30,7 @@ static_library("performance_manager") {
"graph/node_attached_data_impl.h", "graph/node_attached_data_impl.h",
"graph/node_base.cc", "graph/node_base.cc",
"graph/node_base.h", "graph/node_base.h",
"graph/node_data_describer.cc",
"graph/node_type.h", "graph/node_type.h",
"graph/page_node.cc", "graph/page_node.cc",
"graph/page_node_impl.cc", "graph/page_node_impl.cc",
...@@ -71,6 +72,8 @@ static_library("performance_manager") { ...@@ -71,6 +72,8 @@ static_library("performance_manager") {
"public/graph/graph_operations.h", "public/graph/graph_operations.h",
"public/graph/node.h", "public/graph/node.h",
"public/graph/node_attached_data.h", "public/graph/node_attached_data.h",
"public/graph/node_data_describer.h",
"public/graph/node_data_describer_registry.h",
"public/graph/page_node.h", "public/graph/page_node.h",
"public/graph/policies/background_tab_loading_policy.h", "public/graph/policies/background_tab_loading_policy.h",
"public/graph/process_node.h", "public/graph/process_node.h",
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h" #include "base/containers/flat_set.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
...@@ -19,6 +20,8 @@ ...@@ -19,6 +20,8 @@
#include "components/performance_manager/graph/process_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/system_node_impl.h"
#include "components/performance_manager/graph/worker_node_impl.h" #include "components/performance_manager/graph/worker_node_impl.h"
#include "components/performance_manager/public/graph/node_data_describer.h"
#include "components/performance_manager/public/graph/node_data_describer_registry.h"
namespace ukm { namespace ukm {
class UkmEntryBuilder; class UkmEntryBuilder;
...@@ -55,6 +58,97 @@ void RemoveObserverImpl(std::vector<NodeObserverType*>* observers, ...@@ -55,6 +58,97 @@ void RemoveObserverImpl(std::vector<NodeObserverType*>* observers,
DCHECK(it == observers->end()); DCHECK(it == observers->end());
} }
class NodeDataDescriberRegistryImpl : public NodeDataDescriberRegistry {
public:
~NodeDataDescriberRegistryImpl() override;
void RegisterDescriber(const NodeDataDescriber* describer,
base::StringPiece name) override;
void UnregisterDescriber(const NodeDataDescriber* describer) override;
base::Value DescribeFrameNodeData(const FrameNode* node) const override;
base::Value DescribePageNodeData(const PageNode* node) const override;
base::Value DescribeProcessNodeData(const ProcessNode* node) const override;
base::Value DescribeSystemNodeData(const SystemNode* node) const override;
base::Value DescribeWorkerNodeData(const WorkerNode* node) const override;
private:
template <typename NodeType>
base::Value DescribeNodeImpl(
base::Value (NodeDataDescriber::*DescribeFn)(const NodeType*) const,
const NodeType* node) const;
base::flat_map<const NodeDataDescriber*, std::string> describers_;
};
template <typename NodeType>
base::Value NodeDataDescriberRegistryImpl::DescribeNodeImpl(
base::Value (NodeDataDescriber::*Describe)(const NodeType*) const,
const NodeType* node) const {
base::Value result(base::Value::Type::DICTIONARY);
bool inserted = false;
for (const auto& name_and_describer : describers_) {
base::Value description = (name_and_describer.first->*Describe)(node);
if (!description.is_none()) {
DCHECK_EQ(nullptr, result.FindDictKey(name_and_describer.second));
result.SetKey(name_and_describer.second, std::move(description));
inserted = true;
}
}
return inserted ? std::move(result) : base::Value();
}
NodeDataDescriberRegistryImpl::~NodeDataDescriberRegistryImpl() {
// All describers should have unregistered before the graph is destroyed.
DCHECK(describers_.empty());
}
void NodeDataDescriberRegistryImpl::RegisterDescriber(
const NodeDataDescriber* describer,
base::StringPiece name) {
#if DCHECK_IS_ON()
for (const auto& kv : describers_) {
DCHECK_NE(kv.second, name) << "Name must be unique";
}
#endif
bool inserted =
describers_.insert(std::make_pair(describer, name.as_string())).second;
DCHECK(inserted);
}
void NodeDataDescriberRegistryImpl::UnregisterDescriber(
const NodeDataDescriber* describer) {
size_t erased = describers_.erase(describer);
DCHECK_EQ(1u, erased);
}
base::Value NodeDataDescriberRegistryImpl::DescribeFrameNodeData(
const FrameNode* node) const {
return DescribeNodeImpl(&NodeDataDescriber::DescribeFrameNodeData, node);
}
base::Value NodeDataDescriberRegistryImpl::DescribePageNodeData(
const PageNode* node) const {
return DescribeNodeImpl(&NodeDataDescriber::DescribePageNodeData, node);
}
base::Value NodeDataDescriberRegistryImpl::DescribeProcessNodeData(
const ProcessNode* node) const {
return DescribeNodeImpl(&NodeDataDescriber::DescribeProcessNodeData, node);
}
base::Value NodeDataDescriberRegistryImpl::DescribeSystemNodeData(
const SystemNode* node) const {
return DescribeNodeImpl(&NodeDataDescriber::DescribeSystemNodeData, node);
}
base::Value NodeDataDescriberRegistryImpl::DescribeWorkerNodeData(
const WorkerNode* node) const {
return DescribeNodeImpl(&NodeDataDescriber::DescribeWorkerNodeData, node);
}
} // namespace } // namespace
GraphImpl::GraphImpl() { GraphImpl::GraphImpl() {
...@@ -220,6 +314,13 @@ ukm::UkmRecorder* GraphImpl::GetUkmRecorder() const { ...@@ -220,6 +314,13 @@ ukm::UkmRecorder* GraphImpl::GetUkmRecorder() const {
return ukm_recorder(); return ukm_recorder();
} }
NodeDataDescriberRegistry* GraphImpl::GetNodeDataDescriberRegistry() const {
if (!describer_registry_)
describer_registry_ = std::make_unique<NodeDataDescriberRegistryImpl>();
return describer_registry_.get();
}
uintptr_t GraphImpl::GetImplType() const { uintptr_t GraphImpl::GetImplType() const {
return kGraphImplType; return kGraphImplType;
} }
......
...@@ -72,6 +72,7 @@ class GraphImpl : public Graph { ...@@ -72,6 +72,7 @@ class GraphImpl : public Graph {
std::vector<const WorkerNode*> GetAllWorkerNodes() const override; std::vector<const WorkerNode*> GetAllWorkerNodes() const override;
bool IsEmpty() const override; bool IsEmpty() const override;
ukm::UkmRecorder* GetUkmRecorder() const override; ukm::UkmRecorder* GetUkmRecorder() const override;
NodeDataDescriberRegistry* GetNodeDataDescriberRegistry() const override;
uintptr_t GetImplType() const override; uintptr_t GetImplType() const override;
const void* GetImpl() const override; const void* GetImpl() const override;
...@@ -183,6 +184,9 @@ class GraphImpl : public Graph { ...@@ -183,6 +184,9 @@ class GraphImpl : public Graph {
// flat_map. // flat_map.
base::flat_map<GraphOwned*, std::unique_ptr<GraphOwned>> graph_owned_; base::flat_map<GraphOwned*, std::unique_ptr<GraphOwned>> graph_owned_;
// Allocated on first use.
mutable std::unique_ptr<NodeDataDescriberRegistry> describer_registry_;
// User data storage for the graph. // User data storage for the graph.
friend class NodeAttachedDataMapHelper; friend class NodeAttachedDataMapHelper;
using NodeAttachedDataKey = std::pair<const Node*, const void*>; using NodeAttachedDataKey = std::pair<const Node*, const void*>;
......
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include "components/performance_manager/graph/frame_node_impl.h" #include "components/performance_manager/graph/frame_node_impl.h"
#include "components/performance_manager/graph/process_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/system_node_impl.h"
#include "components/performance_manager/public/graph/node_data_describer.h"
#include "components/performance_manager/public/graph/node_data_describer_registry.h"
#include "components/performance_manager/test_support/graph_test_harness.h" #include "components/performance_manager/test_support/graph_test_harness.h"
#include "components/performance_manager/test_support/mock_graphs.h" #include "components/performance_manager/test_support/mock_graphs.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -221,4 +223,125 @@ TEST_F(GraphImplTest, GraphOwned) { ...@@ -221,4 +223,125 @@ TEST_F(GraphImplTest, GraphOwned) {
EXPECT_EQ(2, destructor_count); EXPECT_EQ(2, destructor_count);
} }
namespace {
class TestNodeDataDescriber : public NodeDataDescriber {
public:
explicit TestNodeDataDescriber(base::StringPiece name) : name_(name) {}
base::Value DescribeFrameNodeData(const FrameNode* node) const override {
base::Value list(base::Value::Type::LIST);
list.Append(name_);
list.Append("FrameNode");
return list;
}
base::Value DescribePageNodeData(const PageNode* node) const override {
base::Value list(base::Value::Type::LIST);
list.Append(name_);
list.Append("PageNode");
return list;
}
base::Value DescribeProcessNodeData(const ProcessNode* node) const override {
base::Value list(base::Value::Type::LIST);
list.Append(name_);
list.Append("ProcessNode");
return list;
}
base::Value DescribeSystemNodeData(const SystemNode* node) const override {
base::Value list(base::Value::Type::LIST);
list.Append(name_);
list.Append("SystemNode");
return list;
}
base::Value DescribeWorkerNodeData(const WorkerNode* node) const override {
base::Value list(base::Value::Type::LIST);
list.Append(name_);
list.Append("WorkerNode");
return list;
}
private:
const std::string name_;
};
void AssertDictValueContainsListKey(const base::Value& descr,
const char* key,
const char* s1,
const char* s2) {
ASSERT_TRUE(descr.is_dict());
const base::Value* v = descr.FindListKey(key);
ASSERT_NE(nullptr, v);
const auto list = v->GetList();
ASSERT_EQ(2u, list.size());
ASSERT_EQ(list[0], base::Value(s1));
ASSERT_EQ(list[1], base::Value(s2));
}
} // namespace
TEST_F(GraphImplTest, NodeDataDescribers) {
MockSinglePageInSingleProcessGraph mock_graph(graph());
NodeDataDescriberRegistry* registry = graph()->GetNodeDataDescriberRegistry();
// No describers->no description.
base::Value descr = registry->DescribeFrameNodeData(mock_graph.frame.get());
EXPECT_TRUE(descr.is_none());
// Test that the default impl does nothing.
NodeDataDescriberDefaultImpl default_impl;
registry->RegisterDescriber(&default_impl, "default_impl");
// Test a single non-default describer for each node type.
TestNodeDataDescriber d1("d1");
registry->RegisterDescriber(&d1, "d1");
descr = registry->DescribeFrameNodeData(mock_graph.frame.get());
AssertDictValueContainsListKey(descr, "d1", "d1", "FrameNode");
EXPECT_EQ(1u, descr.DictSize());
descr = registry->DescribePageNodeData(mock_graph.page.get());
AssertDictValueContainsListKey(descr, "d1", "d1", "PageNode");
EXPECT_EQ(1u, descr.DictSize());
descr = registry->DescribeProcessNodeData(mock_graph.process.get());
AssertDictValueContainsListKey(descr, "d1", "d1", "ProcessNode");
EXPECT_EQ(1u, descr.DictSize());
descr =
registry->DescribeSystemNodeData(graph()->FindOrCreateSystemNodeImpl());
AssertDictValueContainsListKey(descr, "d1", "d1", "SystemNode");
EXPECT_EQ(1u, descr.DictSize());
auto worker = CreateNode<WorkerNodeImpl>(WorkerNode::WorkerType::kDedicated,
mock_graph.process.get());
descr = registry->DescribeWorkerNodeData(worker.get());
AssertDictValueContainsListKey(descr, "d1", "d1", "WorkerNode");
EXPECT_EQ(1u, descr.DictSize());
// Unregister the default impl now that it's been verified to say nothing
// about all node types.
registry->UnregisterDescriber(&default_impl);
// Register a second describer and test one node type.
TestNodeDataDescriber d2("d2");
registry->RegisterDescriber(&d2, "d2");
descr = registry->DescribeFrameNodeData(mock_graph.frame.get());
EXPECT_EQ(2u, descr.DictSize());
AssertDictValueContainsListKey(descr, "d1", "d1", "FrameNode");
AssertDictValueContainsListKey(descr, "d2", "d2", "FrameNode");
registry->UnregisterDescriber(&d2);
registry->UnregisterDescriber(&d1);
// No describers after unregistration->no description.
descr = registry->DescribeFrameNodeData(mock_graph.frame.get());
EXPECT_TRUE(descr.is_none());
}
} // namespace performance_manager } // namespace performance_manager
// Copyright 2020 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 "components/performance_manager/public/graph/node_data_describer.h"
namespace performance_manager {
base::Value NodeDataDescriberDefaultImpl::DescribeFrameNodeData(
const FrameNode* node) const {
return base::Value();
}
base::Value NodeDataDescriberDefaultImpl::DescribePageNodeData(
const PageNode* node) const {
return base::Value();
}
base::Value NodeDataDescriberDefaultImpl::DescribeProcessNodeData(
const ProcessNode* node) const {
return base::Value();
}
base::Value NodeDataDescriberDefaultImpl::DescribeSystemNodeData(
const SystemNode* node) const {
return base::Value();
}
base::Value NodeDataDescriberDefaultImpl::DescribeWorkerNodeData(
const WorkerNode* node) const {
return base::Value();
}
} // namespace performance_manager
...@@ -31,6 +31,8 @@ class SystemNodeObserver; ...@@ -31,6 +31,8 @@ class SystemNodeObserver;
class WorkerNode; class WorkerNode;
class WorkerNodeObserver; class WorkerNodeObserver;
class NodeDataDescriberRegistry;
// Represents a graph of the nodes representing a single browser. Maintains a // Represents a graph of the nodes representing a single browser. Maintains a
// set of nodes that can be retrieved in different ways, some indexed. Keeps // set of nodes that can be retrieved in different ways, some indexed. Keeps
// a list of observers that are notified of node addition and removal. // a list of observers that are notified of node addition and removal.
...@@ -86,6 +88,9 @@ class Graph { ...@@ -86,6 +88,9 @@ class Graph {
// Returns the associated UKM recorder if it is defined. // Returns the associated UKM recorder if it is defined.
virtual ukm::UkmRecorder* GetUkmRecorder() const = 0; virtual ukm::UkmRecorder* GetUkmRecorder() const = 0;
// Returns the data describer registry.
virtual NodeDataDescriberRegistry* GetNodeDataDescriberRegistry() const = 0;
// The following functions are implementation detail and should not need to be // The following functions are implementation detail and should not need to be
// used by external clients. They provide the ability to safely downcast to // used by external clients. They provide the ability to safely downcast to
// the underlying implementation. // the underlying implementation.
......
// Copyright 2020 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 COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_H_
#include "base/values.h"
namespace performance_manager {
class FrameNode;
class PageNode;
class ProcessNode;
class SystemNode;
class WorkerNode;
// An interface for decoding node-private data for ultimate display as
// human-comprehensible text to allow diagnosis of node private data.
class NodeDataDescriber {
public:
virtual ~NodeDataDescriber() = default;
virtual base::Value DescribeFrameNodeData(const FrameNode* node) const = 0;
virtual base::Value DescribePageNodeData(const PageNode* node) const = 0;
virtual base::Value DescribeProcessNodeData(
const ProcessNode* node) const = 0;
virtual base::Value DescribeSystemNodeData(const SystemNode* node) const = 0;
virtual base::Value DescribeWorkerNodeData(const WorkerNode* node) const = 0;
};
// A convenience do-nothing implementation of the interface above. Returns
// an is_none() value for all nodes.
class NodeDataDescriberDefaultImpl : public NodeDataDescriber {
public:
base::Value DescribeFrameNodeData(const FrameNode* node) const override;
base::Value DescribePageNodeData(const PageNode* node) const override;
base::Value DescribeProcessNodeData(const ProcessNode* node) const override;
base::Value DescribeSystemNodeData(const SystemNode* node) const override;
base::Value DescribeWorkerNodeData(const WorkerNode* node) const override;
};
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_H_
// Copyright 2020 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 COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_REGISTRY_H_
#define COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_REGISTRY_H_
#include <map>
#include "base/strings/string_piece.h"
#include "base/values.h"
namespace performance_manager {
class FrameNode;
class PageNode;
class ProcessNode;
class SystemNode;
class WorkerNode;
class NodeDataDescriber;
// Allows registering NodeDataDescribers.
class NodeDataDescriberRegistry {
public:
virtual ~NodeDataDescriberRegistry() = default;
// Register |describer| with |name|.
// The |describer| must not be registered already, and |name| must be unique
// to this registration.
virtual void RegisterDescriber(const NodeDataDescriber* describer,
base::StringPiece name) = 0;
// Unregister previously registered |describer|.
virtual void UnregisterDescriber(const NodeDataDescriber* describer) = 0;
// Invoke all registered describers for |node| and return a dictionary from
// their name to their description - if any.
virtual base::Value DescribeFrameNodeData(const FrameNode* node) const = 0;
virtual base::Value DescribePageNodeData(const PageNode* node) const = 0;
virtual base::Value DescribeProcessNodeData(
const ProcessNode* node) const = 0;
virtual base::Value DescribeSystemNodeData(const SystemNode* node) const = 0;
virtual base::Value DescribeWorkerNodeData(const WorkerNode* node) const = 0;
};
} // namespace performance_manager
#endif // COMPONENTS_PERFORMANCE_MANAGER_PUBLIC_GRAPH_NODE_DATA_DESCRIBER_REGISTRY_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment