From 281d30d758dc9060045ada1b3d326bfe3ef668dd Mon Sep 17 00:00:00 2001 From: ssid Date: Fri, 17 Apr 2015 07:04:32 -0700 Subject: [PATCH] Adding V8 api to get memory statistics of spaces in V8::Heap. This is first step towards adding V8 heap statistics to the memory tracing infrastructure. For being able to get useful memory number into the memory dump, v8 needs to provide an external api needs to obtain more information about the heap. So, this Cl extends the api to give information about the memory allocated and used in the spaces. BUG=466141, 476013 LOG=Y Review URL: https://codereview.chromium.org/1058253003 Cr-Commit-Position: refs/heads/master@{#27919} --- include/v8.h | 37 +++++++++++++++++++++++++++++++ src/api.cc | 33 ++++++++++++++++++++++++++++ src/heap/heap.cc | 19 ++++++++++++++++ src/heap/heap.h | 13 +++++++++++ src/heap/spaces.h | 65 +++++++++++++++++++++++++++++++++++++------------------ 5 files changed, 146 insertions(+), 21 deletions(-) diff --git a/include/v8.h b/include/v8.h index e32c104..fa47ac1 100644 --- a/include/v8.h +++ b/include/v8.h @@ -4901,6 +4901,26 @@ class V8_EXPORT HeapStatistics { }; +class HeapSpaceStatistics { + public: + HeapSpaceStatistics(); + const char* space_name() { return space_name_; } + size_t space_size() { return space_size_; } + size_t space_used_size() { return space_used_size_; } + size_t space_available_size() { return space_available_size_; } + size_t physical_space_size() { return physical_space_size_; } + + private: + const char* space_name_; + size_t space_size_; + size_t space_used_size_; + size_t space_available_size_; + size_t physical_space_size_; + + friend class Isolate; +}; + + class RetainedObjectInfo; @@ -5263,6 +5283,23 @@ class V8_EXPORT Isolate { void GetHeapStatistics(HeapStatistics* heap_statistics); /** + * Returns the number of spaces in the heap. + */ + size_t NumberOfHeapSpaces(); + + /** + * Get the memory usage of a space in the heap. + * + * \param space_statistics The HeapSpaceStatistics object to fill in + * statistics. + * \param index The index of the space to get statistics from, which ranges + * from 0 to NumberOfHeapSpaces() - 1. + * \returns true on success. + */ + bool GetHeapSpaceStatistics(HeapSpaceStatistics* space_statistics, + size_t index); + + /** * Get a call stack sample from the isolate. * \param state Execution state. * \param frames Caller allocated buffer to store stack frames. diff --git a/src/api.cc b/src/api.cc index 14d3a82..991b9ee 100644 --- a/src/api.cc +++ b/src/api.cc @@ -30,6 +30,7 @@ #include "src/deoptimizer.h" #include "src/execution.h" #include "src/global-handles.h" +#include "src/heap/spaces.h" #include "src/heap-profiler.h" #include "src/heap-snapshot-generator-inl.h" #include "src/icu_util.h" @@ -5463,6 +5464,13 @@ HeapStatistics::HeapStatistics(): total_heap_size_(0), heap_size_limit_(0) { } +HeapSpaceStatistics::HeapSpaceStatistics(): space_name_(0), + space_size_(0), + space_used_size_(0), + space_available_size_(0), + physical_space_size_(0) { } + + bool v8::V8::InitializeICU(const char* icu_data_file) { return i::InitializeICU(icu_data_file); } @@ -7000,6 +7008,31 @@ void Isolate::GetHeapStatistics(HeapStatistics* heap_statistics) { } +size_t Isolate::NumberOfHeapSpaces() { + return i::LAST_SPACE - i::FIRST_SPACE + 1; +} + + +bool Isolate::GetHeapSpaceStatistics(HeapSpaceStatistics* space_statistics, + size_t index) { + if (!space_statistics) + return false; + if (index > i::LAST_SPACE || index < i::FIRST_SPACE) + return false; + + i::Isolate* isolate = reinterpret_cast(this); + i::Heap* heap = isolate->heap(); + i::Space* space = heap->space(static_cast(index)); + + space_statistics->space_name_ = heap->GetSpaceName(static_cast(index)); + space_statistics->space_size_ = space->CommittedMemory(); + space_statistics->space_used_size_ = space->Size(); + space_statistics->space_available_size_ = space->Available(); + space_statistics->physical_space_size_ = space->CommittedPhysicalMemory(); + return true; +} + + void Isolate::GetStackSample(const RegisterState& state, void** frames, size_t frames_limit, SampleInfo* sample_info) { i::Isolate* isolate = reinterpret_cast(this); diff --git a/src/heap/heap.cc b/src/heap/heap.cc index 38a31bc..4de5358 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -452,6 +452,25 @@ intptr_t Heap::SizeOfObjects() { } +const char* Heap::GetSpaceName(int idx) { + switch (idx) { + case NEW_SPACE: + return "new_space"; + case OLD_SPACE: + return "old_space"; + case MAP_SPACE: + return "map_space"; + case CODE_SPACE: + return "code_space"; + case LO_SPACE: + return "large_object_space"; + default: + UNREACHABLE(); + } + return nullptr; +} + + void Heap::ClearAllICsByKind(Code::Kind kind) { HeapObjectIterator it(code_space()); diff --git a/src/heap/heap.h b/src/heap/heap.h index 4bcfcbb..0a9e30e 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -664,6 +664,19 @@ class Heap { } return NULL; } + Space* space(int idx) { + switch (idx) { + case NEW_SPACE: + return new_space(); + case LO_SPACE: + return lo_space(); + default: + return paged_space(idx); + } + } + + // Returns name of the space. + const char* GetSpaceName(int idx); bool always_allocate() { return always_allocate_scope_depth_ != 0; } Address always_allocate_scope_depth_address() { diff --git a/src/heap/spaces.h b/src/heap/spaces.h index c04a109..74250c7 100644 --- a/src/heap/spaces.h +++ b/src/heap/spaces.h @@ -842,6 +842,15 @@ class Space : public Malloced { // (e.g. see LargeObjectSpace). virtual intptr_t SizeOfObjects() { return Size(); } + // Return the total amount of memory committed for new space. + virtual intptr_t CommittedMemory() = 0; + + // Approximate amount of physical memory committed for this space. + virtual size_t CommittedPhysicalMemory() = 0; + + // Return the available bytes without growing. + virtual intptr_t Available() = 0; + virtual int RoundSizeDownToObjectAlignment(int size) { if (id_ == CODE_SPACE) { return RoundDown(size, kCodeAlignment); @@ -1684,13 +1693,13 @@ class PagedSpace : public Space { // Total amount of memory committed for this space. For paged // spaces this equals the capacity. - intptr_t CommittedMemory() { return Capacity(); } + intptr_t CommittedMemory() override { return Capacity(); } // The maximum amount of memory ever committed for this space. intptr_t MaximumCommittedMemory() { return accounting_stats_.MaxCapacity(); } // Approximate amount of physical memory committed for this space. - size_t CommittedPhysicalMemory(); + size_t CommittedPhysicalMemory() override; struct SizeStats { intptr_t Total() { @@ -1725,17 +1734,17 @@ class PagedSpace : public Space { // The bytes in the linear allocation area are not included in this total // because updating the stats would slow down allocation. New pages are // immediately added to the free list so they show up here. - intptr_t Available() { return free_list_.available(); } + intptr_t Available() override { return free_list_.available(); } // Allocated bytes in this space. Garbage bytes that were not found due to // concurrent sweeping are counted as being allocated! The bytes in the // current linear allocation area (between top and limit) are also counted // here. - virtual intptr_t Size() { return accounting_stats_.Size(); } + intptr_t Size() override { return accounting_stats_.Size(); } // As size, but the bytes in lazily swept pages are estimated and the bytes // in the current linear allocation area are not included. - virtual intptr_t SizeOfObjects(); + intptr_t SizeOfObjects() override; // Wasted bytes in this space. These are just the bytes that were thrown away // due to being too small to use for allocation. They do not include the @@ -1804,7 +1813,7 @@ class PagedSpace : public Space { #ifdef DEBUG // Print meta info and objects in this space. - virtual void Print(); + void Print() override; // Reports statistics for the space void ReportStatistics(); @@ -2129,12 +2138,26 @@ class SemiSpace : public Space { } // If we don't have these here then SemiSpace will be abstract. However - // they should never be called. - virtual intptr_t Size() { + // they should never be called: + + intptr_t Size() override { UNREACHABLE(); return 0; } + intptr_t SizeOfObjects() override { return Size(); } + + intptr_t CommittedMemory() override { + UNREACHABLE(); + return 0; + } + + intptr_t Available() override { + UNREACHABLE(); + return 0; + } + + bool is_committed() { return committed_; } bool Commit(); bool Uncommit(); @@ -2147,7 +2170,7 @@ class SemiSpace : public Space { #endif #ifdef DEBUG - virtual void Print(); + void Print() override; // Validate a range of of addresses in a SemiSpace. // The "from" address must be on a page prior to the "to" address, // in the linked page order, or it must be earlier on the same page. @@ -2177,7 +2200,7 @@ class SemiSpace : public Space { size_t MaximumCommittedMemory() { return maximum_committed_; } // Approximate amount of physical memory committed for this space. - size_t CommittedPhysicalMemory(); + size_t CommittedPhysicalMemory() override; private: // Flips the semispace between being from-space and to-space. @@ -2356,7 +2379,7 @@ class NewSpace : public Space { } // Return the allocated bytes in the active semispace. - virtual intptr_t Size() { + intptr_t Size() override { return pages_used_ * NewSpacePage::kAreaSize + static_cast(top() - to_space_.page_low()); } @@ -2381,7 +2404,7 @@ class NewSpace : public Space { } // Return the total amount of memory committed for new space. - intptr_t CommittedMemory() { + intptr_t CommittedMemory() override { if (from_space_.is_committed()) return 2 * Capacity(); return TotalCapacity(); } @@ -2393,10 +2416,10 @@ class NewSpace : public Space { } // Approximate amount of physical memory committed for this space. - size_t CommittedPhysicalMemory(); + size_t CommittedPhysicalMemory() override; // Return the available bytes without growing. - intptr_t Available() { return Capacity() - Size(); } + intptr_t Available() override { return Capacity() - Size(); } // Return the maximum capacity of a semispace. int MaximumCapacity() { @@ -2513,7 +2536,7 @@ class NewSpace : public Space { #ifdef DEBUG // Print the active semispace. - virtual void Print() { to_space_.Print(); } + void Print() override { to_space_.Print(); } #endif // Iterates the active semispace to collect statistics. @@ -2684,18 +2707,18 @@ class LargeObjectSpace : public Space { bool CanAllocateSize(int size) { return Size() + size <= max_capacity_; } // Available bytes for objects in this space. - inline intptr_t Available(); + inline intptr_t Available() override; - virtual intptr_t Size() { return size_; } + intptr_t Size() override { return size_; } - virtual intptr_t SizeOfObjects() { return objects_size_; } + intptr_t SizeOfObjects() override { return objects_size_; } intptr_t MaximumCommittedMemory() { return maximum_committed_; } - intptr_t CommittedMemory() { return Size(); } + intptr_t CommittedMemory() override { return Size(); } // Approximate amount of physical memory committed for this space. - size_t CommittedPhysicalMemory(); + size_t CommittedPhysicalMemory() override; int PageCount() { return page_count_; } @@ -2723,7 +2746,7 @@ class LargeObjectSpace : public Space { #endif #ifdef DEBUG - virtual void Print(); + void Print() override; void ReportStatistics(); void CollectCodeStatistics(); #endif -- 2.7.4