Commit b9c129fb authored by Lalit Maganti's avatar Lalit Maganti Committed by Commit Bot

memory-infra: fix post order iterator

The iterator should work on the scope of the entire graph as it relies
on shared visited set between processes to do its job.

Bug: 768373
Change-Id: I2be92608c8d709464a32f8f35a10cd5686fc7af9
Reviewed-on: https://chromium-review.googlesource.com/788870Reviewed-by: default avatarPrimiano Tucci <primiano@chromium.org>
Commit-Queue: Lalit Maganti <lalitm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521684}
parent b45f07cc
...@@ -48,6 +48,16 @@ Node* GlobalDumpGraph::CreateNode(Process* process_graph, Node* parent) { ...@@ -48,6 +48,16 @@ Node* GlobalDumpGraph::CreateNode(Process* process_graph, Node* parent) {
return &*all_nodes_.begin(); return &*all_nodes_.begin();
} }
PostOrderIterator GlobalDumpGraph::VisitInDepthFirstPostOrder() {
std::vector<Node*> roots;
for (auto it = process_dump_graphs_.rbegin();
it != process_dump_graphs_.rend(); it++) {
roots.push_back(it->second->root());
}
roots.push_back(shared_memory_graph_->root());
return PostOrderIterator(std::move(roots));
}
Process::Process(base::ProcessId pid, GlobalDumpGraph* global_graph) Process::Process(base::ProcessId pid, GlobalDumpGraph* global_graph)
: pid_(pid), : pid_(pid),
global_graph_(global_graph), global_graph_(global_graph),
...@@ -102,10 +112,6 @@ Node* Process::FindNode(base::StringPiece path) { ...@@ -102,10 +112,6 @@ Node* Process::FindNode(base::StringPiece path) {
return current; return current;
} }
PostOrderIterator Process::VisitInDepthFirstPostOrder() {
return PostOrderIterator(root_);
}
Node::Node(Process* dump_graph, Node* parent) Node::Node(Process* dump_graph, Node* parent)
: dump_graph_(dump_graph), parent_(parent), owns_edge_(nullptr) {} : dump_graph_(dump_graph), parent_(parent), owns_edge_(nullptr) {}
Node::~Node() {} Node::~Node() {}
...@@ -171,9 +177,8 @@ Node::Entry::Entry(std::string value) ...@@ -171,9 +177,8 @@ Node::Entry::Entry(std::string value)
Edge::Edge(Node* source, Node* target, int priority) Edge::Edge(Node* source, Node* target, int priority)
: source_(source), target_(target), priority_(priority) {} : source_(source), target_(target), priority_(priority) {}
PostOrderIterator::PostOrderIterator(Node* root) { PostOrderIterator::PostOrderIterator(std::vector<Node*> roots)
to_visit_.push_back(root); : to_visit_(std::move(roots)) {}
}
PostOrderIterator::PostOrderIterator(PostOrderIterator&& other) = default; PostOrderIterator::PostOrderIterator(PostOrderIterator&& other) = default;
PostOrderIterator::~PostOrderIterator() = default; PostOrderIterator::~PostOrderIterator() = default;
......
...@@ -42,11 +42,6 @@ class GlobalDumpGraph { ...@@ -42,11 +42,6 @@ class GlobalDumpGraph {
// if no such node exists in the provided |graph|. // if no such node exists in the provided |graph|.
GlobalDumpGraph::Node* FindNode(base::StringPiece path); GlobalDumpGraph::Node* FindNode(base::StringPiece path);
// Returns an iterator which yields nodes in the nodes in this graph in
// post-order. That is, children and owners of nodes are returned before the
// node itself.
GlobalDumpGraph::PostOrderIterator VisitInDepthFirstPostOrder();
base::ProcessId pid() const { return pid_; } base::ProcessId pid() const { return pid_; }
GlobalDumpGraph* global_graph() const { return global_graph_; } GlobalDumpGraph* global_graph() const { return global_graph_; }
GlobalDumpGraph::Node* root() const { return root_; } GlobalDumpGraph::Node* root() const { return root_; }
...@@ -179,7 +174,7 @@ class GlobalDumpGraph { ...@@ -179,7 +174,7 @@ class GlobalDumpGraph {
// An iterator-esque class which yields nodes in a depth-first post order. // An iterator-esque class which yields nodes in a depth-first post order.
class PostOrderIterator { class PostOrderIterator {
public: public:
PostOrderIterator(Node* root); PostOrderIterator(std::vector<Node*> root_nodes);
PostOrderIterator(PostOrderIterator&& other); PostOrderIterator(PostOrderIterator&& other);
~PostOrderIterator(); ~PostOrderIterator();
...@@ -208,6 +203,11 @@ class GlobalDumpGraph { ...@@ -208,6 +203,11 @@ class GlobalDumpGraph {
// and edge priority. // and edge priority.
void AddNodeOwnershipEdge(Node* owner, Node* owned, int priority); void AddNodeOwnershipEdge(Node* owner, Node* owned, int priority);
// Returns an iterator which yields nodes in the nodes in this graph in
// post-order. That is, children and owners of nodes are returned before the
// node itself.
PostOrderIterator VisitInDepthFirstPostOrder();
const GuidNodeMap& nodes_by_guid() const { return nodes_by_guid_; } const GuidNodeMap& nodes_by_guid() const { return nodes_by_guid_; }
GlobalDumpGraph::Process* shared_memory_graph() const { GlobalDumpGraph::Process* shared_memory_graph() const {
return shared_memory_graph_.get(); return shared_memory_graph_.get();
......
...@@ -136,32 +136,18 @@ void GraphProcessor::CalculateSizesForGraph(GlobalDumpGraph* global_graph) { ...@@ -136,32 +136,18 @@ void GraphProcessor::CalculateSizesForGraph(GlobalDumpGraph* global_graph) {
// Eighth pass: calculate the size field for nodes by considering the sizes // Eighth pass: calculate the size field for nodes by considering the sizes
// of their children and owners. // of their children and owners.
{ {
auto it = global_graph->shared_memory_graph()->VisitInDepthFirstPostOrder(); auto it = global_graph->VisitInDepthFirstPostOrder();
while (Node* node = it.next()) { while (Node* node = it.next()) {
CalculateSizeForNode(node); CalculateSizeForNode(node);
} }
for (auto& pid_to_process : global_graph->process_dump_graphs()) {
auto it = pid_to_process.second->VisitInDepthFirstPostOrder();
while (Node* node = it.next()) {
CalculateSizeForNode(node);
}
}
} }
// Ninth pass: Calculate not-owned and not-owning sub-sizes of all nodes. // Ninth pass: Calculate not-owned and not-owning sub-sizes of all nodes.
{ {
auto it = global_graph->shared_memory_graph()->VisitInDepthFirstPostOrder(); auto it = global_graph->VisitInDepthFirstPostOrder();
while (Node* node = it.next()) { while (Node* node = it.next()) {
CalculateDumpSubSizes(node); CalculateDumpSubSizes(node);
} }
for (auto& pid_to_process : global_graph->process_dump_graphs()) {
auto it = pid_to_process.second->VisitInDepthFirstPostOrder();
while (Node* node = it.next()) {
CalculateDumpSubSizes(node);
}
}
} }
} }
......
...@@ -9,10 +9,16 @@ ...@@ -9,10 +9,16 @@
namespace memory_instrumentation { namespace memory_instrumentation {
namespace {
using base::trace_event::MemoryAllocatorDumpGuid; using base::trace_event::MemoryAllocatorDumpGuid;
using Node = memory_instrumentation::GlobalDumpGraph::Node; using Node = memory_instrumentation::GlobalDumpGraph::Node;
using Process = memory_instrumentation::GlobalDumpGraph::Process; using Process = memory_instrumentation::GlobalDumpGraph::Process;
const MemoryAllocatorDumpGuid kEmptyGuid;
} // namespace
TEST(GlobalDumpGraphTest, CreateContainerForProcess) { TEST(GlobalDumpGraphTest, CreateContainerForProcess) {
GlobalDumpGraph global_dump_graph; GlobalDumpGraph global_dump_graph;
...@@ -41,39 +47,34 @@ TEST(GlobalDumpGraphTest, AddNodeOwnershipEdge) { ...@@ -41,39 +47,34 @@ TEST(GlobalDumpGraphTest, AddNodeOwnershipEdge) {
TEST(GlobalDumpGraphTest, VisitInDepthFirstPostOrder) { TEST(GlobalDumpGraphTest, VisitInDepthFirstPostOrder) {
GlobalDumpGraph graph; GlobalDumpGraph graph;
Process* process = graph.shared_memory_graph(); Process* process_1 = graph.CreateGraphForProcess(1);
Node* root = process->root(); Process* process_2 = graph.CreateGraphForProcess(2);
Node c1(process, root); Node* c1 = process_1->CreateNode(kEmptyGuid, "c1", false);
Node c2(process, root); Node* c2 = process_1->CreateNode(kEmptyGuid, "c2", false);
Node c2_c1(process, &c2); Node* c2_c1 = process_1->CreateNode(kEmptyGuid, "c2/c1", false);
Node c2_c2(process, &c2); Node* c2_c2 = process_1->CreateNode(kEmptyGuid, "c2/c2", false);
Node c3(process, root);
Node c3_c1(process, &c3); Node* c3 = process_2->CreateNode(kEmptyGuid, "c3", false);
Node c3_c2(process, &c3); Node* c3_c1 = process_2->CreateNode(kEmptyGuid, "c3/c1", false);
Node* c3_c2 = process_2->CreateNode(kEmptyGuid, "c3/c2", false);
root->InsertChild("c1", &c1);
root->InsertChild("c2", &c2);
root->InsertChild("c3", &c3);
c2.InsertChild("c1", &c2_c1);
c2.InsertChild("c2", &c2_c2);
c3.InsertChild("c1", &c3_c1);
c3.InsertChild("c2", &c3_c2);
// |c3_c2| owns |c2_c2|. // |c3_c2| owns |c2_c2|.
graph.AddNodeOwnershipEdge(&c3_c2, &c2_c2, 1); graph.AddNodeOwnershipEdge(c3_c2, c2_c2, 1);
// This method should always call owners and then children before the node // This method should always call owners and then children before the node
// itself. // itself.
auto iterator = process->VisitInDepthFirstPostOrder(); auto iterator = graph.VisitInDepthFirstPostOrder();
ASSERT_EQ(iterator.next(), &c1); ASSERT_EQ(iterator.next(), graph.shared_memory_graph()->root());
ASSERT_EQ(iterator.next(), &c2_c1); ASSERT_EQ(iterator.next(), c1);
ASSERT_EQ(iterator.next(), &c3_c2); ASSERT_EQ(iterator.next(), c2_c1);
ASSERT_EQ(iterator.next(), &c2_c2); ASSERT_EQ(iterator.next(), c3_c2);
ASSERT_EQ(iterator.next(), &c2); ASSERT_EQ(iterator.next(), c2_c2);
ASSERT_EQ(iterator.next(), &c3_c1); ASSERT_EQ(iterator.next(), c2);
ASSERT_EQ(iterator.next(), &c3); ASSERT_EQ(iterator.next(), process_1->root());
ASSERT_EQ(iterator.next(), root); ASSERT_EQ(iterator.next(), c3_c1);
ASSERT_EQ(iterator.next(), c3);
ASSERT_EQ(iterator.next(), process_2->root());
ASSERT_EQ(iterator.next(), nullptr); ASSERT_EQ(iterator.next(), nullptr);
} }
......
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