diff --git a/src/heap-snapshot-generator.cc b/src/heap-snapshot-generator.cc index 5864ad9b43..929064489b 100644 --- a/src/heap-snapshot-generator.cc +++ b/src/heap-snapshot-generator.cc @@ -2743,6 +2743,11 @@ void HeapSnapshotJSONSerializer::SerializeImpl() { if (writer_->aborted()) return; writer_->AddString("],\n"); + writer_->AddString("\"samples\":["); + SerializeSamples(); + if (writer_->aborted()) return; + writer_->AddString("],\n"); + writer_->AddString("\"strings\":["); SerializeStrings(); if (writer_->aborted()) return; @@ -2939,7 +2944,10 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() { JSON_S("function_info_index") "," JSON_S("count") "," JSON_S("size") "," - JSON_S("children")))); + JSON_S("children")) "," + JSON_S("sample_fields") ":" JSON_A( + JSON_S("timestamp_us") "," + JSON_S("last_assigned_id")))); #undef JSON_S #undef JSON_O #undef JSON_A @@ -3028,13 +3036,10 @@ void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { EmbeddedVector buffer; const List& list = tracker->function_info_list(); - bool first_entry = true; for (int i = 0; i < list.length(); i++) { AllocationTracker::FunctionInfo* info = list[i]; int buffer_pos = 0; - if (first_entry) { - first_entry = false; - } else { + if (i > 0) { buffer[buffer_pos++] = ','; } buffer_pos = utoa(info->function_id, buffer, buffer_pos); @@ -3057,6 +3062,34 @@ void HeapSnapshotJSONSerializer::SerializeTraceNodeInfos() { } +void HeapSnapshotJSONSerializer::SerializeSamples() { + const List& samples = + snapshot_->profiler()->heap_object_map()->samples(); + if (samples.is_empty()) return; + base::TimeTicks start_time = samples[0].timestamp; + // The buffer needs space for 2 unsigned ints, 2 commas, \n and \0 + const int kBufferSize = MaxDecimalDigitsIn::kUnsigned + + MaxDecimalDigitsIn::kUnsigned + + 2 + 1 + 1; + EmbeddedVector buffer; + for (int i = 0; i < samples.length(); i++) { + HeapObjectsMap::TimeInterval& sample = samples[i]; + int buffer_pos = 0; + if (i > 0) { + buffer[buffer_pos++] = ','; + } + base::TimeDelta time_delta = sample.timestamp - start_time; + buffer_pos = utoa(time_delta.InMicroseconds(), buffer, buffer_pos); + buffer[buffer_pos++] = ','; + buffer_pos = utoa(sample.last_assigned_id(), buffer, buffer_pos); + buffer[buffer_pos++] = '\n'; + buffer[buffer_pos++] = '\0'; + writer_->AddString(buffer.start()); + } +} + + void HeapSnapshotJSONSerializer::SerializeString(const unsigned char* s) { writer_->AddCharacter('\n'); writer_->AddCharacter('\"'); diff --git a/src/heap-snapshot-generator.h b/src/heap-snapshot-generator.h index 55d36ce946..ef71ce6ff1 100644 --- a/src/heap-snapshot-generator.h +++ b/src/heap-snapshot-generator.h @@ -194,6 +194,16 @@ class HeapSnapshot { class HeapObjectsMap { public: + struct TimeInterval { + explicit TimeInterval(SnapshotObjectId id) + : id(id), size(0), count(0), timestamp(base::TimeTicks::Now()) {} + SnapshotObjectId last_assigned_id() const { return id - kObjectIdStep; } + SnapshotObjectId id; + uint32_t size; + uint32_t count; + base::TimeTicks timestamp; + }; + explicit HeapObjectsMap(Heap* heap); Heap* heap() const { return heap_; } @@ -210,6 +220,7 @@ class HeapObjectsMap { void StopHeapObjectsTracking(); SnapshotObjectId PushHeapObjectsStats(OutputStream* stream); + const List& samples() const { return time_intervals_; } size_t GetUsedMemorySize() const; SnapshotObjectId GenerateId(v8::RetainedObjectInfo* info); @@ -236,12 +247,6 @@ class HeapObjectsMap { unsigned int size; bool accessed; }; - struct TimeInterval { - explicit TimeInterval(SnapshotObjectId id) : id(id), size(0), count(0) { } - SnapshotObjectId id; - uint32_t size; - uint32_t count; - }; SnapshotObjectId next_id_; HashMap entries_map_; @@ -584,6 +589,7 @@ class HeapSnapshotJSONSerializer { void SerializeTraceTree(); void SerializeTraceNode(AllocationTraceNode* node); void SerializeTraceNodeInfos(); + void SerializeSamples(); void SerializeString(const unsigned char* s); void SerializeStrings();