diff --git a/src/flag-definitions.h b/src/flag-definitions.h index f8a800d236..9228944d00 100644 --- a/src/flag-definitions.h +++ b/src/flag-definitions.h @@ -502,6 +502,9 @@ DEFINE_bool(trace_gc_ignore_scavenger, false, "do not print trace line after scavenger collection") DEFINE_bool(print_cumulative_gc_stat, false, "print cumulative GC statistics in name=value format on exit") +DEFINE_bool(print_max_heap_committed, false, + "print statistics of the maximum memory committed for the heap " + "in name=value format on exit") DEFINE_bool(trace_gc_verbose, false, "print more details following each garbage collection") DEFINE_bool(trace_fragmentation, false, diff --git a/src/heap.cc b/src/heap.cc index dfe9c84936..f7751c1a22 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -79,6 +79,7 @@ Heap::Heap() // ConfigureHeap (survived_since_last_expansion_, external_allocation_limit_) // Will be 4 * reserved_semispace_size_ to ensure that young // generation can be aligned to its size. + maximum_committed_(0), survived_since_last_expansion_(0), sweep_generation_(0), always_allocate_scope_depth_(0), @@ -232,6 +233,16 @@ intptr_t Heap::CommittedMemoryExecutable() { } +void Heap::UpdateMaximumCommitted() { + if (!HasBeenSetUp()) return; + + intptr_t current_committed_memory = CommittedMemory(); + if (current_committed_memory > maximum_committed_) { + maximum_committed_ = current_committed_memory; + } +} + + intptr_t Heap::Available() { if (!HasBeenSetUp()) return 0; @@ -441,6 +452,8 @@ void Heap::GarbageCollectionPrologue() { #endif } + UpdateMaximumCommitted(); + #ifdef DEBUG ASSERT(!AllowHeapAllocation::IsAllowed() && gc_state_ == NOT_IN_GC); @@ -506,6 +519,8 @@ void Heap::GarbageCollectionEpilogue() { } } + UpdateMaximumCommitted(); + isolate_->counters()->alive_after_last_gc()->Set( static_cast(SizeOfObjects())); @@ -567,6 +582,9 @@ void Heap::GarbageCollectionEpilogue() { property_cell_space()->CommittedMemory() / KB)); isolate_->counters()->heap_sample_code_space_committed()->AddSample( static_cast(code_space()->CommittedMemory() / KB)); + + isolate_->counters()->heap_sample_maximum_committed()->AddSample( + static_cast(MaximumCommittedMemory() / KB)); } #define UPDATE_COUNTERS_FOR_SPACE(space) \ @@ -6812,6 +6830,8 @@ void Heap::TearDown() { } #endif + UpdateMaximumCommitted(); + if (FLAG_print_cumulative_gc_stat) { PrintF("\n"); PrintF("gc_count=%d ", gc_count_); @@ -6826,6 +6846,31 @@ void Heap::TearDown() { PrintF("\n\n"); } + if (FLAG_print_max_heap_committed) { + PrintF("\n"); + PrintF("maximum_committed_by_heap=%" V8_PTR_PREFIX "d ", + MaximumCommittedMemory()); + PrintF("maximum_committed_by_new_space=%" V8_PTR_PREFIX "d ", + new_space_.MaximumCommittedMemory()); + PrintF("maximum_committed_by_old_pointer_space=%" V8_PTR_PREFIX "d ", + old_data_space_->MaximumCommittedMemory()); + PrintF("maximum_committed_by_old_data_space=%" V8_PTR_PREFIX "d ", + old_pointer_space_->MaximumCommittedMemory()); + PrintF("maximum_committed_by_old_data_space=%" V8_PTR_PREFIX "d ", + old_pointer_space_->MaximumCommittedMemory()); + PrintF("maximum_committed_by_code_space=%" V8_PTR_PREFIX "d ", + code_space_->MaximumCommittedMemory()); + PrintF("maximum_committed_by_map_space=%" V8_PTR_PREFIX "d ", + map_space_->MaximumCommittedMemory()); + PrintF("maximum_committed_by_cell_space=%" V8_PTR_PREFIX "d ", + cell_space_->MaximumCommittedMemory()); + PrintF("maximum_committed_by_property_space=%" V8_PTR_PREFIX "d ", + property_cell_space_->MaximumCommittedMemory()); + PrintF("maximum_committed_by_lo_space=%" V8_PTR_PREFIX "d ", + lo_space_->MaximumCommittedMemory()); + PrintF("\n\n"); + } + TearDownArrayBuffers(); isolate_->global_handles()->TearDown(); diff --git a/src/heap.h b/src/heap.h index 96cda586b7..3a029555ed 100644 --- a/src/heap.h +++ b/src/heap.h @@ -533,6 +533,13 @@ class Heap { // Returns the amount of phyical memory currently committed for the heap. size_t CommittedPhysicalMemory(); + // Returns the maximum amount of memory ever committed for the heap. + intptr_t MaximumCommittedMemory() { return maximum_committed_; } + + // Updates the maximum committed memory for the heap. Should be called + // whenever a space grows. + void UpdateMaximumCommitted(); + // Returns the available bytes in space w/o growing. // Heap doesn't guarantee that it can allocate an object that requires // all available bytes. Check MaxHeapObjectSize() instead. @@ -1888,6 +1895,7 @@ class Heap { int initial_semispace_size_; intptr_t max_old_generation_size_; intptr_t max_executable_size_; + intptr_t maximum_committed_; // For keeping track of how much data has survived // scavenge since last new space expansion. diff --git a/src/spaces.cc b/src/spaces.cc index fe5eeb5e43..f35db6994c 100644 --- a/src/spaces.cc +++ b/src/spaces.cc @@ -1122,6 +1122,11 @@ void PagedSpace::ResetFreeListStatistics() { } +void PagedSpace::IncreaseCapacity(int size) { + accounting_stats_.ExpandSpace(size); +} + + void PagedSpace::ReleasePage(Page* page, bool unlink) { ASSERT(page->LiveBytes() == 0); ASSERT(AreaSize() == page->area_size()); @@ -1511,6 +1516,7 @@ void SemiSpace::SetUp(Address start, initial_capacity_ = RoundDown(initial_capacity, Page::kPageSize); capacity_ = initial_capacity; maximum_capacity_ = RoundDown(maximum_capacity, Page::kPageSize); + maximum_committed_ = 0; committed_ = false; start_ = start; address_mask_ = ~(maximum_capacity - 1); @@ -1543,6 +1549,7 @@ bool SemiSpace::Commit() { current = new_page; } + SetCapacity(capacity_); committed_ = true; Reset(); return true; @@ -1591,7 +1598,7 @@ bool SemiSpace::GrowTo(int new_capacity) { start_ + capacity_, delta, executable())) { return false; } - capacity_ = new_capacity; + SetCapacity(new_capacity); NewSpacePage* last_page = anchor()->prev_page(); ASSERT(last_page != anchor()); for (int i = pages_before; i < pages_after; i++) { @@ -1631,7 +1638,7 @@ bool SemiSpace::ShrinkTo(int new_capacity) { ASSERT((current_page_ >= first_page()) && (current_page_ <= new_last_page)); } - capacity_ = new_capacity; + SetCapacity(new_capacity); return true; } @@ -1694,6 +1701,14 @@ void SemiSpace::Swap(SemiSpace* from, SemiSpace* to) { } +void SemiSpace::SetCapacity(int new_capacity) { + capacity_ = new_capacity; + if (capacity_ > maximum_committed_) { + maximum_committed_ = capacity_; + } +} + + void SemiSpace::set_age_mark(Address mark) { ASSERT(NewSpacePage::FromLimit(mark)->semi_space() == this); age_mark_ = mark; @@ -2938,6 +2953,7 @@ LargeObjectSpace::LargeObjectSpace(Heap* heap, bool LargeObjectSpace::SetUp() { first_page_ = NULL; size_ = 0; + maximum_committed_ = 0; page_count_ = 0; objects_size_ = 0; chunk_map_.Clear(); @@ -2984,6 +3000,10 @@ MaybeObject* LargeObjectSpace::AllocateRaw(int object_size, page->set_next_page(first_page_); first_page_ = page; + if (size_ > maximum_committed_) { + maximum_committed_ = size_; + } + // Register all MemoryChunk::kAlignment-aligned chunks covered by // this large page in the chunk map. uintptr_t base = reinterpret_cast(page) / MemoryChunk::kAlignment; diff --git a/src/spaces.h b/src/spaces.h index 2cd92c59d8..db0415b7b7 100644 --- a/src/spaces.h +++ b/src/spaces.h @@ -1388,6 +1388,7 @@ class AllocationStats BASE_EMBEDDED { // Zero out all the allocation statistics (i.e., no capacity). void Clear() { capacity_ = 0; + max_capacity_ = 0; size_ = 0; waste_ = 0; } @@ -1406,6 +1407,7 @@ class AllocationStats BASE_EMBEDDED { // Accessors for the allocation statistics. intptr_t Capacity() { return capacity_; } + intptr_t MaxCapacity() { return max_capacity_; } intptr_t Size() { return size_; } intptr_t Waste() { return waste_; } @@ -1415,6 +1417,9 @@ class AllocationStats BASE_EMBEDDED { void ExpandSpace(int size_in_bytes) { capacity_ += size_in_bytes; size_ += size_in_bytes; + if (capacity_ > max_capacity_) { + max_capacity_ = capacity_; + } ASSERT(size_ >= 0); } @@ -1448,6 +1453,7 @@ class AllocationStats BASE_EMBEDDED { private: intptr_t capacity_; + intptr_t max_capacity_; intptr_t size_; intptr_t waste_; }; @@ -1689,6 +1695,9 @@ class PagedSpace : public Space { // spaces this equals the capacity. intptr_t CommittedMemory() { 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(); @@ -1795,9 +1804,7 @@ class PagedSpace : public Space { accounting_stats_.AllocateBytes(bytes); } - void IncreaseCapacity(int size) { - accounting_stats_.ExpandSpace(size); - } + void IncreaseCapacity(int size); // Releases an unused page and shrinks the space. void ReleasePage(Page* page, bool unlink); @@ -2207,6 +2214,9 @@ class SemiSpace : public Space { static void Swap(SemiSpace* from, SemiSpace* to); + // Returns the maximum amount of memory ever committed by the semi space. + size_t MaximumCommittedMemory() { return maximum_committed_; } + // Approximate amount of physical memory committed for this space. size_t CommittedPhysicalMemory(); @@ -2215,6 +2225,9 @@ class SemiSpace : public Space { // Copies the flags into the masked positions on all pages in the space. void FlipPages(intptr_t flags, intptr_t flag_mask); + // Updates Capacity and MaximumCommitted based on new capacity. + void SetCapacity(int new_capacity); + NewSpacePage* anchor() { return &anchor_; } // The current and maximum capacity of the space. @@ -2222,6 +2235,8 @@ class SemiSpace : public Space { int maximum_capacity_; int initial_capacity_; + intptr_t maximum_committed_; + // The start address of the space. Address start_; // Used to govern object promotion during mark-compact collection. @@ -2407,6 +2422,12 @@ class NewSpace : public Space { return Capacity(); } + // Return the total amount of memory committed for new space. + intptr_t MaximumCommittedMemory() { + return to_space_.MaximumCommittedMemory() + + from_space_.MaximumCommittedMemory(); + } + // Approximate amount of physical memory committed for this space. size_t CommittedPhysicalMemory(); @@ -2802,6 +2823,10 @@ class LargeObjectSpace : public Space { return objects_size_; } + intptr_t MaximumCommittedMemory() { + return maximum_committed_; + } + intptr_t CommittedMemory() { return Size(); } @@ -2853,6 +2878,7 @@ class LargeObjectSpace : public Space { private: intptr_t max_capacity_; + intptr_t maximum_committed_; // The head of the linked list of large object chunks. LargePage* first_page_; intptr_t size_; // allocated bytes diff --git a/src/v8-counters.h b/src/v8-counters.h index 476021cdbb..3fb659e5b1 100644 --- a/src/v8-counters.h +++ b/src/v8-counters.h @@ -101,6 +101,8 @@ namespace internal { V8.MemoryHeapSamplePropertyCellSpaceCommitted) \ HM(heap_sample_code_space_committed, \ V8.MemoryHeapSampleCodeSpaceCommitted) \ + HM(heap_sample_maximum_committed, \ + V8.MemoryHeapSampleMaximumCommitted) \ // WARNING: STATS_COUNTER_LIST_* is a very large macro that is causing MSVC