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

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: Minor tweak. 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
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 3453 matching lines...) Expand 10 before | Expand all | Expand 10 after
3464 (snapshot_->raw_entries_size() + MB - 1) / MB); 3464 (snapshot_->raw_entries_size() + MB - 1) / MB);
3465 HeapEntry* message = result->AddEntry( 3465 HeapEntry* message = result->AddEntry(
3466 HeapEntry::kString, text, 0, 4, 0, 0); 3466 HeapEntry::kString, text, 0, 4, 0, 0);
3467 root->SetUnidirElementReference(0, 1, message); 3467 root->SetUnidirElementReference(0, 1, message);
3468 result->SetDominatorsToSelf(); 3468 result->SetDominatorsToSelf();
3469 return result; 3469 return result;
3470 } 3470 }
3471 3471
3472 3472
3473 void HeapSnapshotJSONSerializer::SerializeImpl() { 3473 void HeapSnapshotJSONSerializer::SerializeImpl() {
3474 const int node_fields_count = 7;
3475 // type,name,id,self_size,retained_size,dominator,children_index.
3476
3477 List<HeapEntry*>& nodes = *(snapshot_->entries());
yurys 2012/04/11 05:20:05 Consider extracting this loop in a separate method
alexeif 2012/04/11 12:49:57 Done.
3478 // Root must be the first.
3479 ASSERT(nodes.first() == snapshot_->root());
3480 // Rewrite node indexes, so they refer to actual array positions. Do this
3481 // only once.
3482 if (nodes[0]->entry_index() == -1) {
3483 // Nodes start from array 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
3474 writer_->AddCharacter('{'); 3490 writer_->AddCharacter('{');
3475 writer_->AddString("\"snapshot\":{"); 3491 writer_->AddString("\"snapshot\":{");
3476 SerializeSnapshot(); 3492 SerializeSnapshot();
3477 if (writer_->aborted()) return; 3493 if (writer_->aborted()) return;
3478 writer_->AddString("},\n"); 3494 writer_->AddString("},\n");
3479 writer_->AddString("\"nodes\":["); 3495 writer_->AddString("\"nodes\":[");
3480 SerializeNodes(); 3496 SerializeNodes(nodes);
3497 if (writer_->aborted()) return;
3498 writer_->AddString("],\n");
3499 writer_->AddString("\"edges\":[");
3500 SerializeEdges(nodes);
3481 if (writer_->aborted()) return; 3501 if (writer_->aborted()) return;
3482 writer_->AddString("],\n"); 3502 writer_->AddString("],\n");
3483 writer_->AddString("\"strings\":["); 3503 writer_->AddString("\"strings\":[");
3484 SerializeStrings(); 3504 SerializeStrings();
3485 if (writer_->aborted()) return; 3505 if (writer_->aborted()) return;
3486 writer_->AddCharacter(']'); 3506 writer_->AddCharacter(']');
3487 writer_->AddCharacter('}'); 3507 writer_->AddCharacter('}');
3488 writer_->Finalize(); 3508 writer_->Finalize();
3489 } 3509 }
3490 3510
(...skipping 26 matching lines...) Expand all
3517 int result = buffer_pos; 3537 int result = buffer_pos;
3518 do { 3538 do {
3519 int last_digit = value % 10; 3539 int last_digit = value % 10;
3520 buffer[--buffer_pos] = '0' + last_digit; 3540 buffer[--buffer_pos] = '0' + last_digit;
3521 value /= 10; 3541 value /= 10;
3522 } while (value); 3542 } while (value);
3523 return result; 3543 return result;
3524 } 3544 }
3525 3545
3526 3546
3527 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { 3547 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
3548 bool first_edge) {
3528 // The buffer needs space for 3 ints, 3 commas and \0 3549 // The buffer needs space for 3 ints, 3 commas and \0
3529 static const int kBufferSize = 3550 static const int kBufferSize =
3530 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT 3551 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT
3531 EmbeddedVector<char, kBufferSize> buffer; 3552 EmbeddedVector<char, kBufferSize> buffer;
3532 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement 3553 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement
3533 || edge->type() == HeapGraphEdge::kHidden 3554 || edge->type() == HeapGraphEdge::kHidden
3534 || edge->type() == HeapGraphEdge::kWeak 3555 || edge->type() == HeapGraphEdge::kWeak
3535 ? edge->index() : GetStringId(edge->name()); 3556 ? edge->index() : GetStringId(edge->name());
3536 int buffer_pos = 0; 3557 int buffer_pos = 0;
3537 buffer[buffer_pos++] = ','; 3558 if (!first_edge) {
3559 buffer[buffer_pos++] = ',';
3560 }
3538 buffer_pos = itoa(edge->type(), buffer, buffer_pos); 3561 buffer_pos = itoa(edge->type(), buffer, buffer_pos);
3539 buffer[buffer_pos++] = ','; 3562 buffer[buffer_pos++] = ',';
3540 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos); 3563 buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
3541 buffer[buffer_pos++] = ','; 3564 buffer[buffer_pos++] = ',';
3542 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos); 3565 buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos);
3543 buffer[buffer_pos++] = '\0'; 3566 buffer[buffer_pos++] = '\0';
3544 writer_->AddString(buffer.start()); 3567 writer_->AddString(buffer.start());
3545 } 3568 }
3546 3569
3547 3570
3548 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 3571 void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) {
3572 bool first_edge = true;
3573 for (int i = 0; i < nodes.length(); ++i) {
3574 HeapEntry* entry = nodes[i];
3575 Vector<HeapGraphEdge> children = entry->children();
3576 for (int j = 0; j < children.length(); ++j) {
3577 SerializeEdge(&children[j], first_edge);
3578 first_edge = false;
3579 if (writer_->aborted()) return;
3580 }
3581 }
3582 }
3583
3584
3585 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
3586 int edges_index) {
3549 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0 3587 // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
3550 static const int kBufferSize = 3588 static const int kBufferSize =
3551 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT 3589 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
3552 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT 3590 + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
3553 + 7 + 1 + 1; 3591 + 7 + 1 + 1;
3554 EmbeddedVector<char, kBufferSize> buffer; 3592 EmbeddedVector<char, kBufferSize> buffer;
3555 Vector<HeapGraphEdge> children = entry->children();
3556 int buffer_pos = 0; 3593 int buffer_pos = 0;
3557 buffer[buffer_pos++] = '\n'; 3594 buffer[buffer_pos++] = '\n';
3558 buffer[buffer_pos++] = ','; 3595 buffer[buffer_pos++] = ',';
3559 buffer_pos = itoa(entry->type(), buffer, buffer_pos); 3596 buffer_pos = itoa(entry->type(), buffer, buffer_pos);
3560 buffer[buffer_pos++] = ','; 3597 buffer[buffer_pos++] = ',';
3561 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos); 3598 buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
3562 buffer[buffer_pos++] = ','; 3599 buffer[buffer_pos++] = ',';
3563 buffer_pos = itoa(entry->id(), buffer, buffer_pos); 3600 buffer_pos = itoa(entry->id(), buffer, buffer_pos);
3564 buffer[buffer_pos++] = ','; 3601 buffer[buffer_pos++] = ',';
3565 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos); 3602 buffer_pos = itoa(entry->self_size(), buffer, buffer_pos);
3566 buffer[buffer_pos++] = ','; 3603 buffer[buffer_pos++] = ',';
3567 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos); 3604 buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos);
3568 buffer[buffer_pos++] = ','; 3605 buffer[buffer_pos++] = ',';
3569 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos); 3606 buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
3570 buffer[buffer_pos++] = ','; 3607 buffer[buffer_pos++] = ',';
3571 buffer_pos = itoa(children.length(), buffer, buffer_pos); 3608 buffer_pos = itoa(edges_index, buffer, buffer_pos);
3572 buffer[buffer_pos++] = '\0'; 3609 buffer[buffer_pos++] = '\0';
3573 writer_->AddString(buffer.start()); 3610 writer_->AddString(buffer.start());
3574 for (int i = 0; i < children.length(); ++i) {
3575 SerializeEdge(&children[i]);
3576 if (writer_->aborted()) return;
3577 }
3578 } 3611 }
3579 3612
3580 3613
3581 void HeapSnapshotJSONSerializer::SerializeNodes() { 3614 void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) {
3582 // The first (zero) item of nodes array is an object describing node 3615 // The first (zero) item of nodes array is an object describing node
3583 // serialization layout. We use a set of macros to improve 3616 // serialization layout. We use a set of macros to improve
3584 // readability. 3617 // readability.
3585 #define JSON_A(s) "["s"]" 3618 #define JSON_A(s) "["s"]"
3586 #define JSON_O(s) "{"s"}" 3619 #define JSON_O(s) "{"s"}"
3587 #define JSON_S(s) "\""s"\"" 3620 #define JSON_S(s) "\""s"\""
3588 writer_->AddString(JSON_O( 3621 writer_->AddString(JSON_O(
mnaganov (inactive) 2012/04/10 22:28:09 Is this object still the first item of 'nodes' arr
yurys 2012/04/11 05:20:05 I'd rather put the array length at the first item
alexeif 2012/04/11 12:49:57 moved meta info to the snapshot object.
alexeif 2012/04/11 12:49:57 Added node and edges count to the snapshot info.
yurys 2012/04/11 13:07:17 What about the front-end part?
alexeif 2012/04/11 13:10:23 It will follow as soon as we agree on the BE part.
3589 JSON_S("fields") ":" JSON_A( 3622 JSON_S("separate_edges") ":true,"
3590 JSON_S("type") 3623 JSON_S("node_fields") ":" JSON_A(
3591 "," JSON_S("name") 3624 JSON_S("type") ","
mnaganov (inactive) 2012/04/10 22:28:09 Why are you moving commas to the suffix position?
alexeif 2012/04/11 12:49:57 Unless this it the first field. :-) So in this sen
3592 "," JSON_S("id") 3625 JSON_S("name") ","
3593 "," JSON_S("self_size") 3626 JSON_S("id") ","
3594 "," JSON_S("retained_size") 3627 JSON_S("self_size") ","
3595 "," JSON_S("dominator") 3628 JSON_S("retained_size") ","
3596 "," JSON_S("children_count") 3629 JSON_S("dominator") ","
3597 "," JSON_S("children")) 3630 JSON_S("edges_index")) ","
3598 "," JSON_S("types") ":" JSON_A( 3631 JSON_S("node_types") ":" JSON_A(
3599 JSON_A( 3632 JSON_A(
3600 JSON_S("hidden") 3633 JSON_S("hidden") ","
3601 "," JSON_S("array") 3634 JSON_S("array") ","
3602 "," JSON_S("string") 3635 JSON_S("string") ","
3603 "," JSON_S("object") 3636 JSON_S("object") ","
3604 "," JSON_S("code") 3637 JSON_S("code") ","
3605 "," JSON_S("closure") 3638 JSON_S("closure") ","
3606 "," JSON_S("regexp") 3639 JSON_S("regexp") ","
3607 "," JSON_S("number") 3640 JSON_S("number") ","
3608 "," JSON_S("native") 3641 JSON_S("native") ","
3609 "," JSON_S("synthetic")) 3642 JSON_S("synthetic")) ","
3610 "," JSON_S("string") 3643 JSON_S("string") ","
3611 "," JSON_S("number") 3644 JSON_S("number") ","
3612 "," JSON_S("number") 3645 JSON_S("number") ","
3613 "," JSON_S("number") 3646 JSON_S("number") ","
3614 "," JSON_S("number") 3647 JSON_S("number") ","
3615 "," JSON_S("number") 3648 JSON_S("number")) ","
3616 "," JSON_O( 3649 JSON_S("edge_fields") ":" JSON_A(
3617 JSON_S("fields") ":" JSON_A( 3650 JSON_S("type") ","
3618 JSON_S("type") 3651 JSON_S("name_or_index") ","
3619 "," JSON_S("name_or_index") 3652 JSON_S("to_node")) ","
3620 "," JSON_S("to_node")) 3653 JSON_S("edge_types") ":" JSON_A(
3621 "," JSON_S("types") ":" JSON_A( 3654 JSON_A(
3622 JSON_A( 3655 JSON_S("context") ","
3623 JSON_S("context") 3656 JSON_S("element") ","
3624 "," JSON_S("element") 3657 JSON_S("property") ","
3625 "," JSON_S("property") 3658 JSON_S("internal") ","
3626 "," JSON_S("internal") 3659 JSON_S("hidden") ","
3627 "," JSON_S("hidden") 3660 JSON_S("shortcut") ","
3628 "," JSON_S("shortcut") 3661 JSON_S("weak")) ","
3629 "," JSON_S("weak")) 3662 JSON_S("string_or_number") ","
3630 "," JSON_S("string_or_number") 3663 JSON_S("node"))));
3631 "," JSON_S("node"))))));
3632 #undef JSON_S 3664 #undef JSON_S
3633 #undef JSON_O 3665 #undef JSON_O
3634 #undef JSON_A 3666 #undef JSON_A
3635 3667
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. 3668 const int edge_fields_count = 3; // type,name|index,to_node.
3639 3669 int edges_index = 0;
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) { 3670 for (int i = 0; i < nodes.length(); ++i) {
3657 SerializeNode(nodes[i]); 3671 HeapEntry* entry = nodes[i];
3672 SerializeNode(entry, edges_index);
3673 edges_index += entry->children().length() * edge_fields_count;
3658 if (writer_->aborted()) return; 3674 if (writer_->aborted()) return;
3659 } 3675 }
3660 } 3676 }
3661 3677
3662 3678
3663 void HeapSnapshotJSONSerializer::SerializeSnapshot() { 3679 void HeapSnapshotJSONSerializer::SerializeSnapshot() {
3664 writer_->AddString("\"title\":\""); 3680 writer_->AddString("\"title\":\"");
3665 writer_->AddString(snapshot_->title()); 3681 writer_->AddString(snapshot_->title());
3666 writer_->AddString("\""); 3682 writer_->AddString("\"");
3667 writer_->AddString(",\"uid\":"); 3683 writer_->AddString(",\"uid\":");
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
3756 3772
3757 3773
3758 void HeapSnapshotJSONSerializer::SortHashMap( 3774 void HeapSnapshotJSONSerializer::SortHashMap(
3759 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3775 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3760 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3776 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3761 sorted_entries->Add(p); 3777 sorted_entries->Add(p);
3762 sorted_entries->Sort(SortUsingEntryValue); 3778 sorted_entries->Sort(SortUsingEntryValue);
3763 } 3779 }
3764 3780
3765 } } // namespace v8::internal 3781 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698