Revision: 11728
Author:   [email protected]
Date:     Wed Jun  6 03:57:20 2012
Log:      Serialize edge counts instead of indexes in heap snapshot.

The serialized node structure currently holds an index
of its first containment edge in the edges array.
The index can be quite big (up to 7 digits for large snapshots).
The patch changes the serialization format to pass
node containment edge count instead. For most nodes the count
is just a single digit number.
This reduces serialized snapshot size and therefore its transfer time.

Review URL: https://chromiumcodereview.appspot.com/10534008
http://code.google.com/p/v8/source/detail?r=11728

Modified:
 /branches/bleeding_edge/src/profile-generator.cc
 /branches/bleeding_edge/src/profile-generator.h
 /branches/bleeding_edge/test/cctest/test-heap-profiler.cc

=======================================
--- /branches/bleeding_edge/src/profile-generator.cc Fri Jun 1 09:10:52 2012 +++ /branches/bleeding_edge/src/profile-generator.cc Wed Jun 6 03:57:20 2012
@@ -3248,7 +3248,6 @@


 void HeapSnapshotJSONSerializer::SerializeImpl() {
-  List<HeapEntry>& nodes = snapshot_->entries();
   ASSERT(0 == snapshot_->root()->index());
   writer_->AddCharacter('{');
   writer_->AddString("\"snapshot\":{");
@@ -3256,11 +3255,11 @@
   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\":[");
@@ -3302,9 +3301,9 @@

 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
@@ -3324,25 +3323,21 @@
 }


-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;
@@ -3357,19 +3352,17 @@
   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;
   }
 }
@@ -3393,7 +3386,7 @@
         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") ","
=======================================
--- /branches/bleeding_edge/src/profile-generator.h     Fri Jun  1 09:10:52 2012
+++ /branches/bleeding_edge/src/profile-generator.h     Wed Jun  6 03:57:20 2012
@@ -1072,10 +1072,10 @@
   int GetStringId(const char* s);
   int entry_index(HeapEntry* e) { return e->index() * kNodeFieldsCount; }
   void SerializeEdge(HeapGraphEdge* edge, bool first_edge);
-  void SerializeEdges(const List<HeapEntry>& nodes);
+  void SerializeEdges();
   void SerializeImpl();
-  void SerializeNode(HeapEntry* entry, int edges_index);
-  void SerializeNodes(const List<HeapEntry>& nodes);
+  void SerializeNode(HeapEntry* entry);
+  void SerializeNodes();
   void SerializeSnapshot();
   void SerializeString(const unsigned char* s);
   void SerializeStrings();
=======================================
--- /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Fri Jun 1 09:10:52 2012 +++ /branches/bleeding_edge/test/cctest/test-heap-profiler.cc Wed Jun 6 03:57:20 2012
@@ -565,7 +565,7 @@
   // 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"
@@ -575,7 +575,13 @@
       "    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.
@@ -584,8 +590,9 @@
       "  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"
@@ -598,8 +605,7 @@
       "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)");

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to