From 4b54dc52bac8d3303f60d94bcb9838823f436d48 Mon Sep 17 00:00:00 2001 From: "mikhail.naganov@gmail.com" Date: Tue, 21 Feb 2012 14:56:24 +0000 Subject: [PATCH] Speedup the snapshot serialization. Replaced multiple calls to AddNumber with a single AddString. AddNumber may now print the value directly into the output buffer. BUG=none TEST=none Review URL: https://chromiumcodereview.appspot.com/9395087 Patch from Alexei Filippov . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10784 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/profile-generator.cc | 94 ++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 33 deletions(-) diff --git a/src/profile-generator.cc b/src/profile-generator.cc index 8b645ded68..2c8cb14f78 100644 --- a/src/profile-generator.cc +++ b/src/profile-generator.cc @@ -1083,7 +1083,7 @@ void HeapEntry::Print( for (int i = 0; i < ch.length(); ++i) { HeapGraphEdge& edge = ch[i]; const char* edge_prefix = ""; - ScopedVector index(64); + EmbeddedVector index; const char* edge_name = index.start(); switch (edge.type()) { case HeapGraphEdge::kContextVariable: @@ -1164,6 +1164,7 @@ class RetainedSizeCalculator { int retained_size_; }; + void HeapEntry::CalculateExactRetainedSize() { // To calculate retained size, first we paint all reachable nodes in // one color, then we paint (or re-paint) all nodes reachable from @@ -1243,6 +1244,7 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection, } } + HeapSnapshot::~HeapSnapshot() { DeleteArray(raw_entries_); } @@ -1268,6 +1270,7 @@ static void HeapEntryClearPaint(HeapEntry** entry_ptr) { (*entry_ptr)->clear_paint(); } + void HeapSnapshot::ClearPaint() { entries_.Iterate(HeapEntryClearPaint); } @@ -1373,6 +1376,7 @@ static int SortByIds(const T* entry1_ptr, return (*entry1_ptr)->id() < (*entry2_ptr)->id() ? -1 : 1; } + List* HeapSnapshot::GetSortedEntriesList() { if (!entries_sorted_) { entries_.Sort(SortByIds); @@ -3363,6 +3367,17 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() { } +template struct MaxDecimalDigitsIn; +template<> struct MaxDecimalDigitsIn<4> { + static const int kSigned = 11; + static const int kUnsigned = 10; +}; +template<> struct MaxDecimalDigitsIn<8> { + static const int kSigned = 20; + static const int kUnsigned = 20; +}; + + class OutputStreamWriter { public: explicit OutputStreamWriter(v8::OutputStream* stream) @@ -3412,23 +3427,34 @@ class OutputStreamWriter { private: template void AddNumberImpl(T n, const char* format) { - ScopedVector buffer(32); - int result = OS::SNPrintF(buffer, format, n); - USE(result); - ASSERT(result != -1); - AddString(buffer.start()); + // Buffer for the longest value plus trailing \0 + static const int kMaxNumberSize = + MaxDecimalDigitsIn::kUnsigned + 1; + if (chunk_size_ - chunk_pos_ >= kMaxNumberSize) { + int result = OS::SNPrintF( + chunk_.SubVector(chunk_pos_, chunk_size_), format, n); + ASSERT(result != -1); + chunk_pos_ += result; + MaybeWriteChunk(); + } else { + EmbeddedVector buffer; + int result = OS::SNPrintF(buffer, format, n); + USE(result); + ASSERT(result != -1); + AddString(buffer.start()); + } } void MaybeWriteChunk() { ASSERT(chunk_pos_ <= chunk_size_); if (chunk_pos_ == chunk_size_) { WriteChunk(); - chunk_pos_ = 0; } } void WriteChunk() { if (aborted_) return; if (stream_->WriteAsciiChunk(chunk_.start(), chunk_pos_) == v8::OutputStream::kAbort) aborted_ = true; + chunk_pos_ = 0; } v8::OutputStream* stream_; @@ -3438,6 +3464,7 @@ class OutputStreamWriter { bool aborted_; }; + void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) { ASSERT(writer_ == NULL); writer_ = new OutputStreamWriter(stream); @@ -3543,38 +3570,39 @@ int HeapSnapshotJSONSerializer::GetStringId(const char* s) { void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge) { - writer_->AddCharacter(','); - writer_->AddNumber(edge->type()); - writer_->AddCharacter(','); - if (edge->type() == HeapGraphEdge::kElement + // The buffer needs space for 3 ints, 3 commas and \0 + static const int kBufferSize = + MaxDecimalDigitsIn::kSigned * 3 + 3 + 1; // NOLINT + EmbeddedVector buffer; + int edge_name_or_index = edge->type() == HeapGraphEdge::kElement || edge->type() == HeapGraphEdge::kHidden - || edge->type() == HeapGraphEdge::kWeak) { - writer_->AddNumber(edge->index()); - } else { - writer_->AddNumber(GetStringId(edge->name())); - } - writer_->AddCharacter(','); - writer_->AddNumber(GetNodeId(edge->to())); + || edge->type() == HeapGraphEdge::kWeak + ? edge->index() : GetStringId(edge->name()); + int result = OS::SNPrintF(buffer, ",%d,%d,%d", + edge->type(), edge_name_or_index, GetNodeId(edge->to())); + USE(result); + ASSERT(result != -1); + writer_->AddString(buffer.start()); } void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry) { - writer_->AddCharacter('\n'); - writer_->AddCharacter(','); - writer_->AddNumber(entry->type()); - writer_->AddCharacter(','); - writer_->AddNumber(GetStringId(entry->name())); - writer_->AddCharacter(','); - writer_->AddNumber(entry->id()); - writer_->AddCharacter(','); - writer_->AddNumber(entry->self_size()); - writer_->AddCharacter(','); - writer_->AddNumber(entry->RetainedSize(false)); - writer_->AddCharacter(','); - writer_->AddNumber(GetNodeId(entry->dominator())); + // The buffer needs space for 7 ints, 7 commas, \n and \0 + static const int kBufferSize = + MaxDecimalDigitsIn::kSigned * 7 + 7 + 1 + 1; // NOLINT + EmbeddedVector buffer; Vector children = entry->children(); - writer_->AddCharacter(','); - writer_->AddNumber(children.length()); + int result = OS::SNPrintF(buffer, "\n,%d,%d,%d,%d,%d,%d,%d", + entry->type(), + GetStringId(entry->name()), + entry->id(), + entry->self_size(), + entry->RetainedSize(false), + GetNodeId(entry->dominator()), + children.length()); + USE(result); + ASSERT(result != -1); + writer_->AddString(buffer.start()); for (int i = 0; i < children.length(); ++i) { SerializeEdge(&children[i]); if (writer_->aborted()) return;