Skip to content

Commit 6ee8345

Browse files
joyeecheungCommit Bot
authored and
Commit Bot
committed
[heap-profiler] Allow embedder to specify edge names
This patch adds a variant of EmbedderGraph::AddEdge() which allows the embedder to specify the name of an edge. The edges added without name are element edges with auto-incremented indexes while the edges added with names will be internal edges with the specified names for more meaningful output in the heap snapshot. Refs: nodejs/node#21741 Bug: v8:7938 Cq-Include-Trybots: luci.chromium.try:linux_chromium_rel_ng Change-Id: I8feefa2cf6911743e24b3b2024e0e849b0c65cd3 Reviewed-on: https://chromium-review.googlesource.com/1133299 Commit-Queue: Ulan Degenbaev <[email protected]> Reviewed-by: Ulan Degenbaev <[email protected]> Cr-Commit-Position: refs/heads/master@{#54412}
1 parent 9d5822a commit 6ee8345

File tree

3 files changed

+100
-6
lines changed

3 files changed

+100
-6
lines changed

include/v8-profiler.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -703,11 +703,14 @@ class V8_EXPORT EmbedderGraph {
703703
virtual Node* AddNode(std::unique_ptr<Node> node) = 0;
704704

705705
/**
706-
* Adds an edge that represents a strong reference from the given node
707-
* |from| to the given node |to|. The nodes must be added to the graph
706+
* Adds an edge that represents a strong reference from the given
707+
* node |from| to the given node |to|. The nodes must be added to the graph
708708
* before calling this function.
709+
*
710+
* If name is nullptr, the edge will have auto-increment indexes, otherwise
711+
* it will be named accordingly.
709712
*/
710-
virtual void AddEdge(Node* from, Node* to) = 0;
713+
virtual void AddEdge(Node* from, Node* to, const char* name = nullptr) = 0;
711714

712715
virtual ~EmbedderGraph() = default;
713716
};

src/profiler/heap-snapshot-generator.cc

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1957,6 +1957,7 @@ class EmbedderGraphImpl : public EmbedderGraph {
19571957
struct Edge {
19581958
Node* from;
19591959
Node* to;
1960+
const char* name;
19601961
};
19611962

19621963
class V8NodeImpl : public Node {
@@ -1993,7 +1994,9 @@ class EmbedderGraphImpl : public EmbedderGraph {
19931994
return result;
19941995
}
19951996

1996-
void AddEdge(Node* from, Node* to) final { edges_.push_back({from, to}); }
1997+
void AddEdge(Node* from, Node* to, const char* name) final {
1998+
edges_.push_back({from, to, name});
1999+
}
19972000

19982001
const std::vector<std::unique_ptr<Node>>& nodes() { return nodes_; }
19992002
const std::vector<Edge>& edges() { return edges_; }
@@ -2286,8 +2289,13 @@ bool NativeObjectsExplorer::IterateAndExtractReferences(
22862289
int from_index = from->index();
22872290
HeapEntry* to = EntryForEmbedderGraphNode(edge.to);
22882291
if (to) {
2289-
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
2290-
from_index, to);
2292+
if (edge.name == nullptr) {
2293+
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
2294+
from_index, to);
2295+
} else {
2296+
filler_->SetNamedReference(HeapGraphEdge::kInternal, from_index,
2297+
edge.name, to);
2298+
}
22912299
}
22922300
}
22932301
} else {

test/cctest/test-heap-profiler.cc

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ static const char* GetName(const v8::HeapGraphNode* node) {
112112
->name();
113113
}
114114

115+
static const char* GetName(const v8::HeapGraphEdge* edge) {
116+
return const_cast<i::HeapGraphEdge*>(
117+
reinterpret_cast<const i::HeapGraphEdge*>(edge))
118+
->name();
119+
}
120+
115121
static size_t GetSize(const v8::HeapGraphNode* node) {
116122
return const_cast<i::HeapEntry*>(reinterpret_cast<const i::HeapEntry*>(node))
117123
->self_size();
@@ -128,6 +134,18 @@ static const v8::HeapGraphNode* GetChildByName(const v8::HeapGraphNode* node,
128134
return nullptr;
129135
}
130136

137+
static const v8::HeapGraphEdge* GetEdgeByChildName(
138+
const v8::HeapGraphNode* node, const char* name) {
139+
for (int i = 0, count = node->GetChildrenCount(); i < count; ++i) {
140+
const v8::HeapGraphEdge* edge = node->GetChild(i);
141+
const v8::HeapGraphNode* child = edge->GetToNode();
142+
if (!strcmp(name, GetName(child))) {
143+
return edge;
144+
}
145+
}
146+
return nullptr;
147+
}
148+
131149
static const v8::HeapGraphNode* GetRootChild(const v8::HeapSnapshot* snapshot,
132150
const char* name) {
133151
return GetChildByName(snapshot->GetRoot(), name);
@@ -2957,6 +2975,71 @@ TEST(EmbedderGraph) {
29572975
CheckEmbedderGraphSnapshot(env->GetIsolate(), snapshot);
29582976
}
29592977

2978+
void BuildEmbedderGraphWithNamedEdges(v8::Isolate* v8_isolate,
2979+
v8::EmbedderGraph* graph, void* data) {
2980+
using Node = v8::EmbedderGraph::Node;
2981+
Node* global_node = graph->V8Node(*global_object_pointer);
2982+
Node* embedder_node_A = graph->AddNode(
2983+
std::unique_ptr<Node>(new EmbedderNode("EmbedderNodeA", 10)));
2984+
Node* embedder_node_B = graph->AddNode(
2985+
std::unique_ptr<Node>(new EmbedderNode("EmbedderNodeB", 20)));
2986+
Node* embedder_node_C = graph->AddNode(
2987+
std::unique_ptr<Node>(new EmbedderNode("EmbedderNodeC", 30)));
2988+
graph->AddEdge(global_node, embedder_node_A, "global_to_a");
2989+
graph->AddEdge(embedder_node_A, embedder_node_B, "a_to_b");
2990+
graph->AddEdge(embedder_node_B, embedder_node_C);
2991+
}
2992+
2993+
void CheckEmbedderGraphWithNamedEdges(v8::Isolate* isolate,
2994+
const v8::HeapSnapshot* snapshot) {
2995+
const v8::HeapGraphNode* global = GetGlobalObject(snapshot);
2996+
const v8::HeapGraphEdge* global_to_a =
2997+
GetEdgeByChildName(global, "EmbedderNodeA");
2998+
CHECK(global_to_a);
2999+
CHECK_EQ(v8::HeapGraphEdge::kInternal, global_to_a->GetType());
3000+
CHECK(global_to_a->GetName()->IsString());
3001+
CHECK_EQ(0, strcmp("global_to_a", GetName(global_to_a)));
3002+
const v8::HeapGraphNode* embedder_node_A = global_to_a->GetToNode();
3003+
CHECK_EQ(0, strcmp("EmbedderNodeA", GetName(embedder_node_A)));
3004+
CHECK_EQ(10, GetSize(embedder_node_A));
3005+
3006+
const v8::HeapGraphEdge* a_to_b =
3007+
GetEdgeByChildName(embedder_node_A, "EmbedderNodeB");
3008+
CHECK(a_to_b);
3009+
CHECK(a_to_b->GetName()->IsString());
3010+
CHECK_EQ(0, strcmp("a_to_b", GetName(a_to_b)));
3011+
CHECK_EQ(v8::HeapGraphEdge::kInternal, a_to_b->GetType());
3012+
const v8::HeapGraphNode* embedder_node_B = a_to_b->GetToNode();
3013+
CHECK_EQ(0, strcmp("EmbedderNodeB", GetName(embedder_node_B)));
3014+
CHECK_EQ(20, GetSize(embedder_node_B));
3015+
3016+
const v8::HeapGraphEdge* b_to_c =
3017+
GetEdgeByChildName(embedder_node_B, "EmbedderNodeC");
3018+
CHECK(b_to_c);
3019+
CHECK(b_to_c->GetName()->IsNumber());
3020+
CHECK_EQ(v8::HeapGraphEdge::kElement, b_to_c->GetType());
3021+
const v8::HeapGraphNode* embedder_node_C = b_to_c->GetToNode();
3022+
CHECK_EQ(0, strcmp("EmbedderNodeC", GetName(embedder_node_C)));
3023+
CHECK_EQ(30, GetSize(embedder_node_C));
3024+
}
3025+
3026+
TEST(EmbedderGraphWithNamedEdges) {
3027+
i::FLAG_heap_profiler_use_embedder_graph = true;
3028+
LocalContext env;
3029+
v8::HandleScope scope(env->GetIsolate());
3030+
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate());
3031+
v8::Local<v8::Value> global_object =
3032+
v8::Utils::ToLocal(i::Handle<i::JSObject>(
3033+
(isolate->context()->native_context()->global_object()), isolate));
3034+
global_object_pointer = &global_object;
3035+
v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler();
3036+
heap_profiler->AddBuildEmbedderGraphCallback(BuildEmbedderGraphWithNamedEdges,
3037+
nullptr);
3038+
const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot();
3039+
CHECK(ValidateSnapshot(snapshot));
3040+
CheckEmbedderGraphWithNamedEdges(env->GetIsolate(), snapshot);
3041+
}
3042+
29603043
struct GraphBuildingContext {
29613044
int counter = 0;
29623045
};

0 commit comments

Comments
 (0)