| Index: runtime/vm/heap_histogram.cc
|
| diff --git a/runtime/vm/heap_histogram.cc b/runtime/vm/heap_histogram.cc
|
| index 09fd5cdacb78b68a4aef6fec75ab98f271bf580c..bfd7e61a188664ea28bd664bbd7af5c363871816 100644
|
| --- a/runtime/vm/heap_histogram.cc
|
| +++ b/runtime/vm/heap_histogram.cc
|
| @@ -7,6 +7,7 @@
|
| #include "platform/assert.h"
|
| #include "vm/flags.h"
|
| #include "vm/object.h"
|
| +#include "vm/json_stream.h"
|
|
|
| namespace dart {
|
|
|
| @@ -38,8 +39,8 @@ ObjectHistogram::ObjectHistogram(Isolate* isolate) {
|
| major_gc_count_ = 0;
|
| table_length_ = 512;
|
| table_ = reinterpret_cast<Element*>(
|
| - calloc(table_length_, sizeof(Element))); // NOLINT
|
| - for (int index = 0; index < table_length_; index++) {
|
| + calloc(table_length_, sizeof(Element))); // NOLINT
|
| + for (intptr_t index = 0; index < table_length_; index++) {
|
| table_[index].class_id_ = index;
|
| }
|
| }
|
| @@ -51,13 +52,13 @@ ObjectHistogram::~ObjectHistogram() {
|
|
|
|
|
| void ObjectHistogram::RegisterClass(const Class& cls) {
|
| - int class_id = cls.id();
|
| + intptr_t class_id = cls.id();
|
| if (class_id < table_length_) return;
|
| // Resize the table.
|
| - int new_table_length = table_length_ * 2;
|
| + intptr_t new_table_length = table_length_ * 2;
|
| Element* new_table = reinterpret_cast<Element*>(
|
| realloc(table_, new_table_length * sizeof(Element))); // NOLINT
|
| - for (int i = table_length_; i < new_table_length; i++) {
|
| + for (intptr_t i = table_length_; i < new_table_length; i++) {
|
| new_table[i].class_id_ = i;
|
| new_table[i].count_ = 0;
|
| new_table[i].size_ = 0;
|
| @@ -81,30 +82,43 @@ int ObjectHistogram::compare(const Element** a, const Element** b) {
|
| }
|
|
|
|
|
| -void ObjectHistogram::Print() {
|
| - OS::Print("Printing Object Histogram\n");
|
| - OS::Print("____bytes___count_description____________\n");
|
| - // First count the number of non empty entries.
|
| - int length = 0;
|
| - for (int index = 0; index < table_length_; index++) {
|
| +ObjectHistogram::Element** ObjectHistogram::GetSortedArray(
|
| + intptr_t* array_length) {
|
| + intptr_t length = 0;
|
| + for (intptr_t index = 0; index < table_length_; index++) {
|
| if (table_[index].count_ > 0) length++;
|
| }
|
| // Then add them to a new array and sort.
|
| Element** array = reinterpret_cast<Element**>(
|
| calloc(length, sizeof(Element*))); // NOLINT
|
| - int pos = 0;
|
| - for (int index = 0; index < table_length_; index++) {
|
| + intptr_t pos = 0;
|
| + for (intptr_t index = 0; index < table_length_; index++) {
|
| if (table_[index].count_ > 0) array[pos++] = &table_[index];
|
| }
|
| typedef int (*CmpFunc)(const void*, const void*);
|
| qsort(array, length, sizeof(Element*), // NOLINT
|
| reinterpret_cast<CmpFunc>(compare));
|
|
|
| + *array_length = length;
|
| + return array;
|
| +}
|
| +
|
| +void ObjectHistogram::Print() {
|
| + OS::Print("Printing Object Histogram\n");
|
| + OS::Print("____bytes___count_description____________\n");
|
| + // First count the number of non empty entries.
|
| +
|
| + intptr_t length = 0;
|
| + Element** array = NULL;
|
| +
|
| + array = GetSortedArray(&length);
|
| + ASSERT(array != NULL);
|
| +
|
| // Finally print the sorted array.
|
| Class& cls = Class::Handle();
|
| String& str = String::Handle();
|
| Library& lib = Library::Handle();
|
| - for (pos = 0; pos < length; pos++) {
|
| + for (intptr_t pos = 0; pos < length; pos++) {
|
| Element* e = array[pos];
|
| if (e->count_ > 0) {
|
| cls = isolate_->class_table()->At(e->class_id_);
|
| @@ -130,4 +144,62 @@ void ObjectHistogram::Print() {
|
| free(array);
|
| }
|
|
|
| +void ObjectHistogram::PrintToJSONStream(JSONStream* stream) {
|
| + intptr_t length = 0;
|
| + Element** array = NULL;
|
| +
|
| + array = GetSortedArray(&length);
|
| + ASSERT(array != NULL);
|
| +
|
| + // Finally print the sorted array.
|
| + Class& cls = Class::Handle();
|
| + String& str = String::Handle();
|
| + Library& lib = Library::Handle();
|
| +
|
| + intptr_t size_sum = 0;
|
| + intptr_t count_sum = 0;
|
| + stream->OpenObject();
|
| + stream->PrintProperty("type", "ObjectHistogram");
|
| + stream->OpenArray("properties");
|
| + stream->PrintValue("size");
|
| + stream->PrintValue("count");
|
| + stream->CloseArray();
|
| + stream->OpenArray("members");
|
| + for (intptr_t pos = 0; pos < length; pos++) {
|
| + Element* e = array[pos];
|
| + if (e->count_ > 0) {
|
| + cls = isolate_->class_table()->At(e->class_id_);
|
| + str = cls.Name();
|
| + lib = cls.library();
|
| + stream->OpenObject();
|
| + stream->PrintProperty("type", "ObjectHistogramEntry");
|
| + // It should not be possible to overflow here because the total
|
| + // size of the heap is bounded and we are dividing the value
|
| + // by the number of major gcs that have occurred.
|
| + size_sum += (e->size_ / major_gc_count_);
|
| + count_sum += (e->count_ / major_gc_count_);
|
| + stream->PrintProperty("size", e->size_ / major_gc_count_);
|
| + stream->PrintProperty("count", e->count_ / major_gc_count_);
|
| + stream->PrintProperty("name", str.ToCString());
|
| + if (lib.IsNull()) {
|
| + stream->PrintProperty("category", "");
|
| + } else {
|
| + str = lib.url();
|
| + stream->PrintProperty("category", str.ToCString());
|
| + }
|
| + stream->CloseObject();
|
| + }
|
| + }
|
| + stream->CloseArray();
|
| + stream->OpenObject("sums");
|
| + stream->PrintProperty("size", size_sum);
|
| + stream->PrintProperty("count", count_sum);
|
| + stream->CloseObject();
|
| + stream->CloseObject();
|
| +
|
| + // Deallocate the array for sorting.
|
| + free(array);
|
| +}
|
| +
|
| +
|
| } // namespace dart
|
|
|