Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/profile-generator.cc

Issue 10037004: Split nodes and edges into separate arrays in heap snapshot serialization. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Update to the snapshot structure desciption. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1127 const char* title, 1127 const char* title,
1128 unsigned uid) 1128 unsigned uid)
1129 : collection_(collection), 1129 : collection_(collection),
1130 type_(type), 1130 type_(type),
1131 title_(title), 1131 title_(title),
1132 uid_(uid), 1132 uid_(uid),
1133 root_entry_(NULL), 1133 root_entry_(NULL),
1134 gc_roots_entry_(NULL), 1134 gc_roots_entry_(NULL),
1135 natives_root_entry_(NULL), 1135 natives_root_entry_(NULL),
1136 raw_entries_(NULL), 1136 raw_entries_(NULL),
1137 number_of_edges_(0),
1137 max_snapshot_js_object_id_(0) { 1138 max_snapshot_js_object_id_(0) {
1138 STATIC_CHECK( 1139 STATIC_CHECK(
1139 sizeof(HeapGraphEdge) == 1140 sizeof(HeapGraphEdge) ==
1140 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 1141 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize);
1141 STATIC_CHECK( 1142 STATIC_CHECK(
1142 sizeof(HeapEntry) == 1143 sizeof(HeapEntry) ==
1143 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 1144 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
1144 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 1145 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
1145 gc_subroot_entries_[i] = NULL; 1146 gc_subroot_entries_[i] = NULL;
1146 } 1147 }
(...skipping 13 matching lines...) Expand all
1160 1161
1161 void HeapSnapshot::RememberLastJSObjectId() { 1162 void HeapSnapshot::RememberLastJSObjectId() {
1162 max_snapshot_js_object_id_ = collection_->last_assigned_id(); 1163 max_snapshot_js_object_id_ = collection_->last_assigned_id();
1163 } 1164 }
1164 1165
1165 1166
1166 void HeapSnapshot::AllocateEntries(int entries_count, 1167 void HeapSnapshot::AllocateEntries(int entries_count,
1167 int children_count, 1168 int children_count,
1168 int retainers_count) { 1169 int retainers_count) {
1169 ASSERT(raw_entries_ == NULL); 1170 ASSERT(raw_entries_ == NULL);
1171 number_of_edges_ = children_count;
1170 raw_entries_size_ = 1172 raw_entries_size_ =
1171 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); 1173 HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1172 raw_entries_ = NewArray<char>(raw_entries_size_); 1174 raw_entries_ = NewArray<char>(raw_entries_size_);
1173 } 1175 }
1174 1176
1175 1177
1176 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { 1178 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1177 (*entry_ptr)->clear_paint(); 1179 (*entry_ptr)->clear_paint();
1178 } 1180 }
1179 1181
(...skipping 2283 matching lines...) Expand 10 before | Expand all | Expand 10 after
3463 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB, 3465 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB,
3464 (snapshot_->raw_entries_size() + MB - 1) / MB); 3466 (snapshot_->raw_entries_size() + MB - 1) / MB);
3465 HeapEntry* message = result->AddEntry( 3467 HeapEntry* message = result->AddEntry(
3466 HeapEntry::kString, text, 0, 4, 0, 0); 3468 HeapEntry::kString, text, 0, 4, 0, 0);
3467 root->SetUnidirElementReference(0, 1, message); 3469 root->SetUnidirElementReference(0, 1, message);
3468 result->SetDominatorsToSelf(); 3470 result->SetDominatorsToSelf();
3469 return result; 3471 return result;
3470 } 3472 }
3471 3473
3472 3474
3475 void HeapSnapshotJSONSerializer::CalculateNodeIndexes(
3476 const List<HeapEntry*>& nodes) {
3477 // type,name,id,self_size,retained_size,dominator,children_index.
3478 const int node_fields_count = 7;
3479 // Root must be the first.
3480 ASSERT(nodes.first() == snapshot_->root());
3481 // Rewrite node indexes, so they refer to actual array positions. Do this
3482 // only once.
3483 if (nodes[0]->entry_index() == -1) {
3484 int index = 0;
3485 for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) {
3486 nodes[i]->set_entry_index(index);
3487 }
3488 }
3489 }
3490
3491
3473 void HeapSnapshotJSONSerializer::SerializeImpl() { 3492 void HeapSnapshotJSONSerializer::SerializeImpl() {
3493 List<HeapEntry*>& nodes = *(snapshot_->entries());
3494 CalculateNodeIndexes(nodes);
3474 writer_->AddCharacter('{'); 3495 writer_->AddCharacter('{');
3475 writer_->AddString("\"snapshot\":{"); 3496 writer_->AddString("\"snapshot\":{");
3476 SerializeSnapshot(); 3497 SerializeSnapshot();
3477 if (writer_->aborted()) return; 3498 if (writer_->aborted()) return;
3478 writer_->AddString("},\n"); 3499 writer_->AddString("},\n");
3479 writer_->AddString("\"nodes\":["); 3500 writer_->AddString("\"nodes\":[");
3480 SerializeNodes(); 3501 SerializeNodes(nodes);
3502 if (writer_->aborted()) return;
3503 writer_->AddString("],\n");
3504 writer_->AddString("\"edges\":[");
3505 SerializeEdges(nodes);
3481 if (writer_->aborted()) return; 3506 if (writer_->aborted()) return;
3482 writer_->AddString("],\n"); 3507 writer_->AddString("],\n");
3483 writer_->AddString("\"strings\":["); 3508 writer_->AddString("\"strings\":[");
3484 SerializeStrings(); 3509 SerializeStrings();
3485 if (writer_->aborted()) return; 3510 if (writer_->aborted()) return;
3486 writer_->AddCharacter(']'); 3511 writer_->AddCharacter(']');
3487 writer_->AddCharacter('}'); 3512 writer_->AddCharacter('}');
3488 writer_->Finalize(); 3513 writer_->Finalize();
3489 } 3514 }
3490 3515
(...skipping 26 matching lines...) Expand all
3517 int result = buffer_pos; 3542 int result = buffer_pos;
3518 do { 3543 do {
3519 int last_digit = value % 10; 3544 int last_digit = value % 10;
3520 buffer[--buffer_pos] = '0' + last_digit; 3545 buffer[--buffer_pos] = '0' + last_digit;
3521 value /= 10; 3546 value /= 10;
3522 } while (value); 3547 } while (value);
3523 return result; 3548 return result;
3524 } 3549 }
3525 3550
3526 3551
3527 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { 3552 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
3553 bool first_edge) {
3528 // The buffer needs space for 3 ints, 3 commas and \0 3554 // The buffer needs space for 3 ints, 3 commas and \0
3529 static const int kBufferSize = 3555 static const int kBufferSize =
3530 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT 3556 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT
3531 EmbeddedVector<char, kBufferSize> buffer; 3557 EmbeddedVector<char, kBufferSize> buffer;
3532 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 3558 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement
3533 || edge->type() == HeapGraphEdge::kHidden 3559 || edge->type() == HeapGraphEdge::kHidden
3534 || edge->type() == HeapGraphEdge::kWeak 3560 || edge->type() == HeapGraphEdge::kWeak
3535 ? edge->index() : GetStringId(edge->name()); 3561 ? edge->index() : GetStringId(edge->name());
3536 int buffer_pos = 0; 3562 int buffer_pos = 0;
3537 buffer[buffer_pos++] = ','; 3563 if (!first_edge) {
3564 buffer[buffer_pos++] = ',';
3565 }
3538 buffer_pos = itoa(edge->type(), buffer, buffer_pos); 3566 buffer_pos = itoa(edge->type(), buffer, buffer_pos);
3539 buffer[buffer_pos++] = ','; 3567 buffer[buffer_pos++] = ',';
3540 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); 3568 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
3541 buffer[buffer_pos++] = ','; 3569 buffer[buffer_pos++] = ',';
3542 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos); 3570 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos);
3543 buffer[buffer_pos++] = '\0'; 3571 buffer[buffer_pos++] = '\0';
3544 writer_->AddString(buffer.start()); 3572 writer_->AddString(buffer.start());
3545 } 3573 }
3546 3574
3547 3575
3548 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 3576 void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) {
3577 bool first_edge = true;
3578 for (int i = 0; i < nodes.length(); ++i) {
3579 HeapEntry* entry = nodes[i];
3580 Vector<HeapGraphEdge> children = entry->children();
3581 for (int j = 0; j < children.length(); ++j) {
3582 SerializeEdge(&children[j], first_edge);
3583 first_edge = false;
3584 if (writer_->aborted()) return;
3585 }
3586 }
3587 }
3588
3589
3590 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
3591 int edges_index) {
3549 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 3592 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
3550 static const int kBufferSize = 3593 static const int kBufferSize =
3551 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT 3594 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
3552 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT 3595 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
3553 + 7 + 1 + 1; 3596 + 7 + 1 + 1;
3554 EmbeddedVector<char, kBufferSize> buffer; 3597 EmbeddedVector<char, kBufferSize> buffer;
3555 Vector<HeapGraphEdge> children = entry->children();
3556 int buffer_pos = 0; 3598 int buffer_pos = 0;
3557 buffer[buffer_pos++] = '\n'; 3599 buffer[buffer_pos++] = '\n';
3558 buffer[buffer_pos++] = ','; 3600 if (entry->entry_index() != 0) {
3601 buffer[buffer_pos++] = ',';
3602 }
3559 buffer_pos = itoa(entry->type(), buffer, buffer_pos); 3603 buffer_pos = itoa(entry->type(), buffer, buffer_pos);
3560 buffer[buffer_pos++] = ','; 3604 buffer[buffer_pos++] = ',';
3561 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos); 3605 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
3562 buffer[buffer_pos++] = ','; 3606 buffer[buffer_pos++] = ',';
3563 buffer_pos = itoa(entry->id(), buffer, buffer_pos); 3607 buffer_pos = itoa(entry->id(), buffer, buffer_pos);
3564 buffer[buffer_pos++] = ','; 3608 buffer[buffer_pos++] = ',';
3565 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos); 3609 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos);
3566 buffer[buffer_pos++] = ','; 3610 buffer[buffer_pos++] = ',';
3567 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos); 3611 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos);
3568 buffer[buffer_pos++] = ','; 3612 buffer[buffer_pos++] = ',';
3569 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos); 3613 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
3570 buffer[buffer_pos++] = ','; 3614 buffer[buffer_pos++] = ',';
3571 buffer_pos = itoa(children.length(), buffer, buffer_pos); 3615 buffer_pos = itoa(edges_index, buffer, buffer_pos);
3572 buffer[buffer_pos++] = '\0'; 3616 buffer[buffer_pos++] = '\0';
3573 writer_->AddString(buffer.start()); 3617 writer_->AddString(buffer.start());
3574 for (int i = 0; i < children.length(); ++i) { 3618 }
3575 SerializeEdge(&children[i]); 3619
3620
3621 void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) {
3622 const int edge_fields_count = 3; // type,name|index,to_node.
3623 int edges_index = 0;
3624 for (int i = 0; i < nodes.length(); ++i) {
3625 HeapEntry* entry = nodes[i];
3626 SerializeNode(entry, edges_index);
3627 edges_index += entry->children().length() * edge_fields_count;
3576 if (writer_->aborted()) return; 3628 if (writer_->aborted()) return;
3577 } 3629 }
3578 } 3630 }
3579
3580
3581 void HeapSnapshotJSONSerializer::SerializeNodes() {
3582 // The first (zero) item of nodes array is an object describing node
3583 // serialization layout. We use a set of macros to improve
3584 // readability.
3585 #define JSON_A(s) "["s"]"
3586 #define JSON_O(s) "{"s"}"
3587 #define JSON_S(s) "\""s"\""
3588 writer_->AddString(JSON_O(
3589 JSON_S("fields") ":" JSON_A(
3590 JSON_S("type")
3591 "," JSON_S("name")
3592 "," JSON_S("id")
3593 "," JSON_S("self_size")
3594 "," JSON_S("retained_size")
3595 "," JSON_S("dominator")
3596 "," JSON_S("children_count")
3597 "," JSON_S("children"))
3598 "," JSON_S("types") ":" JSON_A(
3599 JSON_A(
3600 JSON_S("hidden")
3601 "," JSON_S("array")
3602 "," JSON_S("string")
3603 "," JSON_S("object")
3604 "," JSON_S("code")
3605 "," JSON_S("closure")
3606 "," JSON_S("regexp")
3607 "," JSON_S("number")
3608 "," JSON_S("native")
3609 "," JSON_S("synthetic"))
3610 "," JSON_S("string")
3611 "," JSON_S("number")
3612 "," JSON_S("number")
3613 "," JSON_S("number")
3614 "," JSON_S("number")
3615 "," JSON_S("number")
3616 "," JSON_O(
3617 JSON_S("fields") ":" JSON_A(
3618 JSON_S("type")
3619 "," JSON_S("name_or_index")
3620 "," JSON_S("to_node"))
3621 "," JSON_S("types") ":" JSON_A(
3622 JSON_A(
3623 JSON_S("context")
3624 "," JSON_S("element")
3625 "," JSON_S("property")
3626 "," JSON_S("internal")
3627 "," JSON_S("hidden")
3628 "," JSON_S("shortcut")
3629 "," JSON_S("weak"))
3630 "," JSON_S("string_or_number")
3631 "," JSON_S("node"))))));
3632 #undef JSON_S
3633 #undef JSON_O
3634 #undef JSON_A
3635
3636 const int node_fields_count = 7;
3637 // type,name,id,self_size,retained_size,dominator,children_count.
3638 const int edge_fields_count = 3; // type,name|index,to_node.
3639
3640 List<HeapEntry*>& nodes = *(snapshot_->entries());
3641 // Root must be the first.
3642 ASSERT(nodes.first() == snapshot_->root());
3643 // Rewrite node indexes, so they refer to actual array positions. Do this
3644 // only once.
3645 if (nodes[0]->entry_index() == -1) {
3646 // Nodes start from array index 1.
3647 int index = 1;
3648 for (int i = 0; i < nodes.length(); ++i) {
3649 HeapEntry* node = nodes[i];
3650 node->set_entry_index(index);
3651 index += node_fields_count +
3652 node->children().length() * edge_fields_count;
3653 }
3654 }
3655
3656 for (int i = 0; i < nodes.length(); ++i) {
3657 SerializeNode(nodes[i]);
3658 if (writer_->aborted()) return;
3659 }
3660 }
3661 3631
3662 3632
3663 void HeapSnapshotJSONSerializer::SerializeSnapshot() { 3633 void HeapSnapshotJSONSerializer::SerializeSnapshot() {
3664 writer_->AddString("\"title\":\""); 3634 writer_->AddString("\"title\":\"");
3665 writer_->AddString(snapshot_->title()); 3635 writer_->AddString(snapshot_->title());
3666 writer_->AddString("\""); 3636 writer_->AddString("\"");
3667 writer_->AddString(",\"uid\":"); 3637 writer_->AddString(",\"uid\":");
3668 writer_->AddNumber(snapshot_->uid()); 3638 writer_->AddNumber(snapshot_->uid());
3639 writer_->AddString(",\"meta\":");
3640 // The object describing node serialization layout.
3641 // We use a set of macros to improve readability.
3642 #define JSON_A(s) "["s"]"
3643 #define JSON_O(s) "{"s"}"
3644 #define JSON_S(s) "\""s"\""
3645 writer_->AddString(JSON_O(
3646 JSON_S("node_fields") ":" JSON_A(
3647 JSON_S("type") ","
3648 JSON_S("name") ","
3649 JSON_S("id") ","
3650 JSON_S("self_size") ","
3651 JSON_S("retained_size") ","
3652 JSON_S("dominator") ","
3653 JSON_S("edges_index")) ","
3654 JSON_S("node_types") ":" JSON_A(
3655 JSON_A(
3656 JSON_S("hidden") ","
3657 JSON_S("array") ","
3658 JSON_S("string") ","
3659 JSON_S("object") ","
3660 JSON_S("code") ","
3661 JSON_S("closure") ","
3662 JSON_S("regexp") ","
3663 JSON_S("number") ","
3664 JSON_S("native") ","
3665 JSON_S("synthetic")) ","
3666 JSON_S("string") ","
3667 JSON_S("number") ","
3668 JSON_S("number") ","
3669 JSON_S("number") ","
3670 JSON_S("number") ","
3671 JSON_S("number")) ","
3672 JSON_S("edge_fields") ":" JSON_A(
3673 JSON_S("type") ","
3674 JSON_S("name_or_index") ","
3675 JSON_S("to_node")) ","
3676 JSON_S("edge_types") ":" JSON_A(
3677 JSON_A(
3678 JSON_S("context") ","
3679 JSON_S("element") ","
3680 JSON_S("property") ","
3681 JSON_S("internal") ","
3682 JSON_S("hidden") ","
3683 JSON_S("shortcut") ","
3684 JSON_S("weak")) ","
3685 JSON_S("string_or_number") ","
3686 JSON_S("node"))));
3687 #undef JSON_S
3688 #undef JSON_O
3689 #undef JSON_A
3690 writer_->AddString(",\"node_count\":");
3691 writer_->AddNumber(snapshot_->entries()->length());
3692 writer_->AddString(",\"edge_count\":");
3693 writer_->AddNumber(snapshot_->number_of_edges());
3669 } 3694 }
3670 3695
3671 3696
3672 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) { 3697 static void WriteUChar(OutputStreamWriter* w, unibrow::uchar u) {
3673 static const char hex_chars[] = "0123456789ABCDEF"; 3698 static const char hex_chars[] = "0123456789ABCDEF";
3674 w->AddString("\\u"); 3699 w->AddString("\\u");
3675 w->AddCharacter(hex_chars[(u >> 12) & 0xf]); 3700 w->AddCharacter(hex_chars[(u >> 12) & 0xf]);
3676 w->AddCharacter(hex_chars[(u >> 8) & 0xf]); 3701 w->AddCharacter(hex_chars[(u >> 8) & 0xf]);
3677 w->AddCharacter(hex_chars[(u >> 4) & 0xf]); 3702 w->AddCharacter(hex_chars[(u >> 4) & 0xf]);
3678 w->AddCharacter(hex_chars[u & 0xf]); 3703 w->AddCharacter(hex_chars[u & 0xf]);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
3756 3781
3757 3782
3758 void HeapSnapshotJSONSerializer::SortHashMap( 3783 void HeapSnapshotJSONSerializer::SortHashMap(
3759 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3784 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3760 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3785 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3761 sorted_entries->Add(p); 3786 sorted_entries->Add(p);
3762 sorted_entries->Sort(SortUsingEntryValue); 3787 sorted_entries->Sort(SortUsingEntryValue);
3763 } 3788 }
3764 3789
3765 } } // namespace v8::internal 3790 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/profile-generator.h ('k') | test/cctest/test-heap-profiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698