void HeapSnapshotJSONSerializer::SerializeImpl() {
- List<HeapEntry>& nodes = snapshot_->entries();
ASSERT(0 == snapshot_->root()->index());
writer_->AddCharacter('{');
writer_->AddString("\"snapshot\":{");
if (writer_->aborted()) return;
writer_->AddString("},\n");
writer_->AddString("\"nodes\":[");
- SerializeNodes(nodes);
+ SerializeNodes();
if (writer_->aborted()) return;
writer_->AddString("],\n");
writer_->AddString("\"edges\":[");
- SerializeEdges(nodes);
+ SerializeEdges();
if (writer_->aborted()) return;
writer_->AddString("],\n");
writer_->AddString("\"strings\":[");
void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
bool first_edge) {
- // The buffer needs space for 3 ints, 3 commas and \0
+ // The buffer needs space for 3 unsigned ints, 3 commas and \0
static const int kBufferSize =
- MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT
+ MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned * 3 + 3 + 1; // NOLINT
EmbeddedVector<char, kBufferSize> buffer;
int edge_name_or_index = edge->type() == HeapGraphEdge::kElement
|| edge->type() == HeapGraphEdge::kHidden
}
-void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry>& nodes) {
- bool first_edge = true;
- for (int i = 0; i < nodes.length(); ++i) {
- HeapEntry* entry = &nodes[i];
- Vector<HeapGraphEdge*> children = entry->children();
- for (int j = 0; j < children.length(); ++j) {
- SerializeEdge(children[j], first_edge);
- first_edge = false;
- if (writer_->aborted()) return;
- }
+void HeapSnapshotJSONSerializer::SerializeEdges() {
+ List<HeapGraphEdge*>& edges = snapshot_->children();
+ for (int i = 0; i < edges.length(); ++i) {
+ ASSERT(i == 0 ||
+ edges[i - 1]->from()->index() <= edges[i]->from()->index());
+ SerializeEdge(edges[i], i == 0);
+ if (writer_->aborted()) return;
}
}
-void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
- int edges_index) {
- // The buffer needs space for 5 uint32_t, 5 commas, \n and \0
+void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) {
+ // The buffer needs space for 5 unsigned ints, 5 commas, \n and \0
static const int kBufferSize =
- 5 * MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
+ 5 * MaxDecimalDigitsIn<sizeof(unsigned)>::kUnsigned // NOLINT
+ 5 + 1 + 1;
EmbeddedVector<char, kBufferSize> buffer;
int buffer_pos = 0;
buffer[buffer_pos++] = ',';
buffer_pos = utoa(entry->self_size(), buffer, buffer_pos);
buffer[buffer_pos++] = ',';
- buffer_pos = utoa(edges_index, buffer, buffer_pos);
+ buffer_pos = utoa(entry->children_count(), buffer, buffer_pos);
buffer[buffer_pos++] = '\n';
buffer[buffer_pos++] = '\0';
writer_->AddString(buffer.start());
}
-void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry>& nodes) {
- int edges_index = 0;
- for (int i = 0; i < nodes.length(); ++i) {
- HeapEntry* entry = &nodes[i];
- SerializeNode(entry, edges_index);
- edges_index += entry->children().length() * kEdgeFieldsCount;
+void HeapSnapshotJSONSerializer::SerializeNodes() {
+ List<HeapEntry>& entries = snapshot_->entries();
+ for (int i = 0; i < entries.length(); ++i) {
+ SerializeNode(&entries[i]);
if (writer_->aborted()) return;
}
}
JSON_S("name") ","
JSON_S("id") ","
JSON_S("self_size") ","
- JSON_S("edges_index")) ","
+ JSON_S("edge_count")) ","
JSON_S("node_types") ":" JSON_A(
JSON_A(
JSON_S("hidden") ","
// Get node and edge "member" offsets.
v8::Local<v8::Value> meta_analysis_result = CompileRun(
"var meta = parsed.snapshot.meta;\n"
- "var edges_index_offset = meta.node_fields.indexOf('edges_index');\n"
+ "var edge_count_offset = meta.node_fields.indexOf('edge_count');\n"
"var node_fields_count = meta.node_fields.length;\n"
"var edge_fields_count = meta.edge_fields.length;\n"
"var edge_type_offset = meta.edge_fields.indexOf('type');\n"
" meta.edge_types[edge_type_offset].indexOf('property');\n"
"var shortcut_type ="
" meta.edge_types[edge_type_offset].indexOf('shortcut');\n"
- "parsed.nodes.concat(0, 0, 0, 0, 0, 0, parsed.edges.length);");
+ "var node_count = parsed.nodes.length / node_fields_count;\n"
+ "var first_edge_indexes = parsed.first_edge_indexes = [];\n"
+ "for (var i = 0, first_edge_index = 0; i < node_count; ++i) {\n"
+ " first_edge_indexes[i] = first_edge_index;\n"
+ " first_edge_index += edge_fields_count *\n"
+ " parsed.nodes[i * node_fields_count + edge_count_offset];\n"
+ "}\n");
CHECK(!meta_analysis_result.IsEmpty());
// A helper function for processing encoded nodes.
" var nodes = parsed.nodes;\n"
" var edges = parsed.edges;\n"
" var strings = parsed.strings;\n"
- " for (var i = nodes[pos + edges_index_offset],\n"
- " count = nodes[pos + node_fields_count + edges_index_offset];\n"
+ " var node_ordinal = pos / node_fields_count;\n"
+ " for (var i = parsed.first_edge_indexes[node_ordinal],\n"
+ " count = parsed.first_edge_indexes[node_ordinal + 1];\n"
" i < count; i += edge_fields_count) {\n"
" if (edges[i + edge_type_offset] === prop_type\n"
" && strings[edges[i + edge_name_offset]] === prop_name)\n"
"GetChildPosByProperty(\n"
" GetChildPosByProperty(\n"
" GetChildPosByProperty("
- " parsed.edges[parsed.nodes[edges_index_offset]"
- " + edge_to_node_offset],"
+ " parsed.edges[edge_to_node_offset],"
" \"b\", property_type),\n"
" \"x\", property_type),"
" \"s\", property_type)");