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

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

Issue 9395087: Speedup the snapshot serialization. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add a constant for decimal length. Created 8 years, 10 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 | « no previous file | no next file » | 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 1065 matching lines...) Expand 10 before | Expand all | Expand 10 after
1076 OS::Print("\\n"); 1076 OS::Print("\\n");
1077 ++c; 1077 ++c;
1078 } 1078 }
1079 OS::Print("\"\n"); 1079 OS::Print("\"\n");
1080 } 1080 }
1081 if (--max_depth == 0) return; 1081 if (--max_depth == 0) return;
1082 Vector<HeapGraphEdge> ch = children(); 1082 Vector<HeapGraphEdge> ch = children();
1083 for (int i = 0; i < ch.length(); ++i) { 1083 for (int i = 0; i < ch.length(); ++i) {
1084 HeapGraphEdge& edge = ch[i]; 1084 HeapGraphEdge& edge = ch[i];
1085 const char* edge_prefix = ""; 1085 const char* edge_prefix = "";
1086 ScopedVector<char> index(64); 1086 EmbeddedVector<char, 64> index;
1087 const char* edge_name = index.start(); 1087 const char* edge_name = index.start();
1088 switch (edge.type()) { 1088 switch (edge.type()) {
1089 case HeapGraphEdge::kContextVariable: 1089 case HeapGraphEdge::kContextVariable:
1090 edge_prefix = "#"; 1090 edge_prefix = "#";
1091 edge_name = edge.name(); 1091 edge_name = edge.name();
1092 break; 1092 break;
1093 case HeapGraphEdge::kElement: 1093 case HeapGraphEdge::kElement:
1094 OS::SNPrintF(index, "%d", edge.index()); 1094 OS::SNPrintF(index, "%d", edge.index());
1095 break; 1095 break;
1096 case HeapGraphEdge::kInternal: 1096 case HeapGraphEdge::kInternal:
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
1157 void Apply(HeapEntry** entry_ptr) { 1157 void Apply(HeapEntry** entry_ptr) {
1158 if ((*entry_ptr)->painted_reachable()) { 1158 if ((*entry_ptr)->painted_reachable()) {
1159 retained_size_ += (*entry_ptr)->self_size(); 1159 retained_size_ += (*entry_ptr)->self_size();
1160 } 1160 }
1161 } 1161 }
1162 1162
1163 private: 1163 private:
1164 int retained_size_; 1164 int retained_size_;
1165 }; 1165 };
1166 1166
1167
1167 void HeapEntry::CalculateExactRetainedSize() { 1168 void HeapEntry::CalculateExactRetainedSize() {
1168 // To calculate retained size, first we paint all reachable nodes in 1169 // To calculate retained size, first we paint all reachable nodes in
1169 // one color, then we paint (or re-paint) all nodes reachable from 1170 // one color, then we paint (or re-paint) all nodes reachable from
1170 // other nodes with a different color. Then we sum up self sizes of 1171 // other nodes with a different color. Then we sum up self sizes of
1171 // nodes painted with the first color. 1172 // nodes painted with the first color.
1172 snapshot()->ClearPaint(); 1173 snapshot()->ClearPaint();
1173 PaintAllReachable(); 1174 PaintAllReachable();
1174 1175
1175 List<HeapEntry*> list(10); 1176 List<HeapEntry*> list(10);
1176 HeapEntry* root = snapshot()->root(); 1177 HeapEntry* root = snapshot()->root();
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1236 sizeof(HeapGraphEdge) == 1237 sizeof(HeapGraphEdge) ==
1237 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize); 1238 SnapshotSizeConstants<kPointerSize>::kExpectedHeapGraphEdgeSize);
1238 STATIC_ASSERT( 1239 STATIC_ASSERT(
1239 sizeof(HeapEntry) == 1240 sizeof(HeapEntry) ==
1240 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize); 1241 SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
1241 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) { 1242 for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
1242 gc_subroot_entries_[i] = NULL; 1243 gc_subroot_entries_[i] = NULL;
1243 } 1244 }
1244 } 1245 }
1245 1246
1247
1246 HeapSnapshot::~HeapSnapshot() { 1248 HeapSnapshot::~HeapSnapshot() {
1247 DeleteArray(raw_entries_); 1249 DeleteArray(raw_entries_);
1248 } 1250 }
1249 1251
1250 1252
1251 void HeapSnapshot::Delete() { 1253 void HeapSnapshot::Delete() {
1252 collection_->RemoveSnapshot(this); 1254 collection_->RemoveSnapshot(this);
1253 delete this; 1255 delete this;
1254 } 1256 }
1255 1257
1256 1258
1257 void HeapSnapshot::AllocateEntries(int entries_count, 1259 void HeapSnapshot::AllocateEntries(int entries_count,
1258 int children_count, 1260 int children_count,
1259 int retainers_count) { 1261 int retainers_count) {
1260 ASSERT(raw_entries_ == NULL); 1262 ASSERT(raw_entries_ == NULL);
1261 raw_entries_size_ = 1263 raw_entries_size_ =
1262 HeapEntry::EntriesSize(entries_count, children_count, retainers_count); 1264 HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1263 raw_entries_ = NewArray<char>(raw_entries_size_); 1265 raw_entries_ = NewArray<char>(raw_entries_size_);
1264 } 1266 }
1265 1267
1266 1268
1267 static void HeapEntryClearPaint(HeapEntry** entry_ptr) { 1269 static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1268 (*entry_ptr)->clear_paint(); 1270 (*entry_ptr)->clear_paint();
1269 } 1271 }
1270 1272
1273
1271 void HeapSnapshot::ClearPaint() { 1274 void HeapSnapshot::ClearPaint() {
1272 entries_.Iterate(HeapEntryClearPaint); 1275 entries_.Iterate(HeapEntryClearPaint);
1273 } 1276 }
1274 1277
1275 1278
1276 HeapEntry* HeapSnapshot::AddRootEntry(int children_count) { 1279 HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
1277 ASSERT(root_entry_ == NULL); 1280 ASSERT(root_entry_ == NULL);
1278 return (root_entry_ = AddEntry(HeapEntry::kObject, 1281 return (root_entry_ = AddEntry(HeapEntry::kObject,
1279 "", 1282 "",
1280 HeapObjectsMap::kInternalRootObjectId, 1283 HeapObjectsMap::kInternalRootObjectId,
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
1366 } 1369 }
1367 1370
1368 1371
1369 template<class T> 1372 template<class T>
1370 static int SortByIds(const T* entry1_ptr, 1373 static int SortByIds(const T* entry1_ptr,
1371 const T* entry2_ptr) { 1374 const T* entry2_ptr) {
1372 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0; 1375 if ((*entry1_ptr)->id() == (*entry2_ptr)->id()) return 0;
1373 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; 1376 return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1;
1374 } 1377 }
1375 1378
1379
1376 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() { 1380 List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() {
1377 if (!entries_sorted_) { 1381 if (!entries_sorted_) {
1378 entries_.Sort(SortByIds); 1382 entries_.Sort(SortByIds);
1379 entries_sorted_ = true; 1383 entries_sorted_ = true;
1380 } 1384 }
1381 return &entries_; 1385 return &entries_;
1382 } 1386 }
1383 1387
1384 1388
1385 void HeapSnapshot::Print(int max_depth) { 1389 void HeapSnapshot::Print(int max_depth) {
(...skipping 1970 matching lines...) Expand 10 before | Expand all | Expand 10 after
3356 dominator != entry; 3360 dominator != entry;
3357 entry = dominator, dominator = entry->dominator()) { 3361 entry = dominator, dominator = entry->dominator()) {
3358 dominator->add_retained_size(entry_size); 3362 dominator->add_retained_size(entry_size);
3359 } 3363 }
3360 if (!ProgressReport()) return false; 3364 if (!ProgressReport()) return false;
3361 } 3365 }
3362 return true; 3366 return true;
3363 } 3367 }
3364 3368
3365 3369
3370 template<int bytes> struct MaxDecimalDigitsIn;
3371 template<> struct MaxDecimalDigitsIn<4> {
3372 static const int kSigned = 11;
3373 static const int kUnsigned = 10;
3374 };
3375 template<> struct MaxDecimalDigitsIn<8> {
3376 static const int kSigned = 20;
3377 static const int kUnsigned = 20;
3378 };
3379
3380
3366 class OutputStreamWriter { 3381 class OutputStreamWriter {
3367 public: 3382 public:
3368 explicit OutputStreamWriter(v8::OutputStream* stream) 3383 explicit OutputStreamWriter(v8::OutputStream* stream)
3369 : stream_(stream), 3384 : stream_(stream),
3370 chunk_size_(stream->GetChunkSize()), 3385 chunk_size_(stream->GetChunkSize()),
3371 chunk_(chunk_size_), 3386 chunk_(chunk_size_),
3372 chunk_pos_(0), 3387 chunk_pos_(0),
3373 aborted_(false) { 3388 aborted_(false) {
3374 ASSERT(chunk_size_ > 0); 3389 ASSERT(chunk_size_ > 0);
3375 } 3390 }
(...skipping 29 matching lines...) Expand all
3405 ASSERT(chunk_pos_ < chunk_size_); 3420 ASSERT(chunk_pos_ < chunk_size_);
3406 if (chunk_pos_ != 0) { 3421 if (chunk_pos_ != 0) {
3407 WriteChunk(); 3422 WriteChunk();
3408 } 3423 }
3409 stream_->EndOfStream(); 3424 stream_->EndOfStream();
3410 } 3425 }
3411 3426
3412 private: 3427 private:
3413 template<typename T> 3428 template<typename T>
3414 void AddNumberImpl(T n, const char* format) { 3429 void AddNumberImpl(T n, const char* format) {
3415 ScopedVector<char> buffer(32); 3430 // Buffer for long long value plus trailing \0
3416 int result = OS::SNPrintF(buffer, format, n); 3431 static const int kMaxNumberSize =
3417 USE(result); 3432 MaxDecimalDigitsIn<sizeof(long long)>::kUnsigned + 1; // NOLINT
mnaganov (inactive) 2012/02/21 14:21:54 I will change "long long" to "T" (and update the c
3418 ASSERT(result != -1); 3433 if (chunk_size_ - chunk_pos_ >= kMaxNumberSize) {
3419 AddString(buffer.start()); 3434 int result = OS::SNPrintF(
3435 chunk_.SubVector(chunk_pos_, chunk_size_), format, n);
3436 ASSERT(result != -1);
3437 chunk_pos_ += result;
3438 MaybeWriteChunk();
3439 } else {
3440 EmbeddedVector<char, kMaxNumberSize> buffer;
3441 int result = OS::SNPrintF(buffer, format, n);
3442 USE(result);
3443 ASSERT(result != -1);
3444 AddString(buffer.start());
3445 }
3420 } 3446 }
3421 void MaybeWriteChunk() { 3447 void MaybeWriteChunk() {
3422 ASSERT(chunk_pos_ <= chunk_size_); 3448 ASSERT(chunk_pos_ <= chunk_size_);
3423 if (chunk_pos_ == chunk_size_) { 3449 if (chunk_pos_ == chunk_size_) {
3424 WriteChunk(); 3450 WriteChunk();
3425 chunk_pos_ = 0;
3426 } 3451 }
3427 } 3452 }
3428 void WriteChunk() { 3453 void WriteChunk() {
3429 if (aborted_) return; 3454 if (aborted_) return;
3430 if (stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_) == 3455 if (stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_) ==
3431 v8::OutputStream::kAbort) aborted_ = true; 3456 v8::OutputStream::kAbort) aborted_ = true;
3457 chunk_pos_ = 0;
3432 } 3458 }
3433 3459
3434 v8::OutputStream* stream_; 3460 v8::OutputStream* stream_;
3435 int chunk_size_; 3461 int chunk_size_;
3436 ScopedVector<char> chunk_; 3462 ScopedVector<char> chunk_;
3437 int chunk_pos_; 3463 int chunk_pos_;
3438 bool aborted_; 3464 bool aborted_;
3439 }; 3465 };
3440 3466
3467
3441 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { 3468 void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
3442 ASSERT(writer_ == NULL); 3469 ASSERT(writer_ == NULL);
3443 writer_ = new OutputStreamWriter(stream); 3470 writer_ = new OutputStreamWriter(stream);
3444 3471
3445 HeapSnapshot* original_snapshot = NULL; 3472 HeapSnapshot* original_snapshot = NULL;
3446 if (snapshot_->raw_entries_size() >= 3473 if (snapshot_->raw_entries_size() >=
3447 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) { 3474 SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) {
3448 // The snapshot is too big. Serialize a fake snapshot. 3475 // The snapshot is too big. Serialize a fake snapshot.
3449 original_snapshot = snapshot_; 3476 original_snapshot = snapshot_;
3450 snapshot_ = CreateFakeSnapshot(); 3477 snapshot_ = CreateFakeSnapshot();
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
3536 HashMap::Entry* cache_entry = strings_.Lookup( 3563 HashMap::Entry* cache_entry = strings_.Lookup(
3537 const_cast<char*>(s), ObjectHash(s), true); 3564 const_cast<char*>(s), ObjectHash(s), true);
3538 if (cache_entry->value == NULL) { 3565 if (cache_entry->value == NULL) {
3539 cache_entry->value = reinterpret_cast<void*>(next_string_id_++); 3566 cache_entry->value = reinterpret_cast<void*>(next_string_id_++);
3540 } 3567 }
3541 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value)); 3568 return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
3542 } 3569 }
3543 3570
3544 3571
3545 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { 3572 void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) {
3546 writer_->AddCharacter(','); 3573 // The buffer needs space for 3 ints, 3 commas and \0
3547 writer_->AddNumber(edge->type()); 3574 static const int kBufferSize =
3548 writer_->AddCharacter(','); 3575 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 3 + 3 + 1; // NOLINT
3549 if (edge->type() == HeapGraphEdge::kElement 3576 EmbeddedVector<char, kBufferSize> buffer;
3577 int edge_name_or_index = edge->type() == HeapGraphEdge::kElement
3550 || edge->type() == HeapGraphEdge::kHidden 3578 || edge->type() == HeapGraphEdge::kHidden
3551 || edge->type() == HeapGraphEdge::kWeak) { 3579 || edge->type() == HeapGraphEdge::kWeak
3552 writer_->AddNumber(edge->index()); 3580 ? edge->index() : GetStringId(edge->name());
3553 } else { 3581 int result = OS::SNPrintF(buffer, ",%d,%d,%d",
3554 writer_->AddNumber(GetStringId(edge->name())); 3582 edge->type(), edge_name_or_index, GetNodeId(edge->to()));
3555 } 3583 USE(result);
3556 writer_->AddCharacter(','); 3584 ASSERT(result != -1);
3557 writer_->AddNumber(GetNodeId(edge->to())); 3585 writer_->AddString(buffer.start());
3558 } 3586 }
3559 3587
3560 3588
3561 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { 3589 void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) {
3562 writer_->AddCharacter('\n'); 3590 // The buffer needs space for 7 ints, 7 commas, \n and \0
3563 writer_->AddCharacter(','); 3591 static const int kBufferSize =
3564 writer_->AddNumber(entry->type()); 3592 MaxDecimalDigitsIn<sizeof(int)>::kSigned * 7 + 7 + 1 + 1; // NOLINT
3565 writer_->AddCharacter(','); 3593 EmbeddedVector<char, kBufferSize> buffer;
3566 writer_->AddNumber(GetStringId(entry->name()));
3567 writer_->AddCharacter(',');
3568 writer_->AddNumber(entry->id());
3569 writer_->AddCharacter(',');
3570 writer_->AddNumber(entry->self_size());
3571 writer_->AddCharacter(',');
3572 writer_->AddNumber(entry->RetainedSize(false));
3573 writer_->AddCharacter(',');
3574 writer_->AddNumber(GetNodeId(entry->dominator()));
3575 Vector<HeapGraphEdge> children = entry->children(); 3594 Vector<HeapGraphEdge> children = entry->children();
3576 writer_->AddCharacter(','); 3595 int result = OS::SNPrintF(buffer, "\n,%d,%d,%d,%d,%d,%d,%d",
3577 writer_->AddNumber(children.length()); 3596 entry->type(),
3597 GetStringId(entry->name()),
3598 entry->id(),
3599 entry->self_size(),
3600 entry->RetainedSize(false),
3601 GetNodeId(entry->dominator()),
3602 children.length());
3603 USE(result);
3604 ASSERT(result != -1);
3605 writer_->AddString(buffer.start());
3578 for (int i = 0; i < children.length(); ++i) { 3606 for (int i = 0; i < children.length(); ++i) {
3579 SerializeEdge(&children[i]); 3607 SerializeEdge(&children[i]);
3580 if (writer_->aborted()) return; 3608 if (writer_->aborted()) return;
3581 } 3609 }
3582 } 3610 }
3583 3611
3584 3612
3585 void HeapSnapshotJSONSerializer::SerializeNodes() { 3613 void HeapSnapshotJSONSerializer::SerializeNodes() {
3586 // The first (zero) item of nodes array is an object describing node 3614 // The first (zero) item of nodes array is an object describing node
3587 // serialization layout. We use a set of macros to improve 3615 // serialization layout. We use a set of macros to improve
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
3758 3786
3759 3787
3760 void HeapSnapshotJSONSerializer::SortHashMap( 3788 void HeapSnapshotJSONSerializer::SortHashMap(
3761 HashMap* map, List<HashMap::Entry*>* sorted_entries) { 3789 HashMap* map, List<HashMap::Entry*>* sorted_entries) {
3762 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p)) 3790 for (HashMap::Entry* p = map->Start(); p != NULL; p = map->Next(p))
3763 sorted_entries->Add(p); 3791 sorted_entries->Add(p);
3764 sorted_entries->Sort(SortUsingEntryValue); 3792 sorted_entries->Sort(SortUsingEntryValue);
3765 } 3793 }
3766 3794
3767 } } // namespace v8::internal 3795 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698