From 4b913965a9f6bd22038ca1cf63efd2edad01c5cf Mon Sep 17 00:00:00 2001 From: "mstarzinger@chromium.org" Date: Wed, 25 Jan 2012 13:46:42 +0000 Subject: [PATCH] Fix responsiveness of high promotion mode heuristics. This changes the heuristics for the high promotion mode to be checked on all GCs (including scavenges), so that changes in the applications behavior are recognized earlier. It also fixes miscalculations in the survival counter and rate which caused heuristics to fail completely. R=vegorov@chromium.org BUG=v8:1899 Review URL: https://chromiumcodereview.appspot.com/9196003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10500 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/heap.cc | 74 ++++++++++++++++++++++++++++++++--------------------- src/heap.h | 24 +++++++++++++---- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/heap.cc b/src/heap.cc index b5a0bc5cb1..3b5dc826b7 100644 --- a/src/heap.cc +++ b/src/heap.cc @@ -695,12 +695,18 @@ void Heap::UpdateSurvivalRateTrend(int start_new_space_size) { (static_cast(young_survivors_after_last_gc_) * 100) / start_new_space_size; - if (survival_rate > kYoungSurvivalRateThreshold) { + if (survival_rate > kYoungSurvivalRateHighThreshold) { high_survival_rate_period_length_++; } else { high_survival_rate_period_length_ = 0; } + if (survival_rate < kYoungSurvivalRateLowThreshold) { + low_survival_rate_period_length_++; + } else { + low_survival_rate_period_length_ = 0; + } + double survival_rate_diff = survival_rate_ - survival_rate; if (survival_rate_diff > kYoungSurvivalRateAllowedDeviation) { @@ -760,32 +766,6 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, UpdateSurvivalRateTrend(start_new_space_size); - if (!new_space_high_promotion_mode_active_ && - new_space_.Capacity() == new_space_.MaximumCapacity() && - IsStableOrIncreasingSurvivalTrend() && - IsHighSurvivalRate()) { - // Stable high survival rates even though young generation is at - // maximum capacity indicates that most objects will be promoted. - // To decrease scavenger pauses and final mark-sweep pauses, we - // have to limit maximal capacity of the young generation. - new_space_high_promotion_mode_active_ = true; - if (FLAG_trace_gc) { - PrintF("Limited new space size due to high promotion rate: %d MB\n", - new_space_.InitialCapacity() / MB); - } - } else if (new_space_high_promotion_mode_active_ && - IsDecreasingSurvivalTrend() && - !IsHighSurvivalRate()) { - // Decreasing low survival rates might indicate that the above high - // promotion mode is over and we should allow the young generation - // to grow again. - new_space_high_promotion_mode_active_ = false; - if (FLAG_trace_gc) { - PrintF("Unlimited new space size due to low promotion rate: %d MB\n", - new_space_.MaximumCapacity() / MB); - } - } - size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSize(); if (high_survival_rate_during_scavenges && @@ -815,6 +795,32 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, UpdateSurvivalRateTrend(start_new_space_size); } + if (!new_space_high_promotion_mode_active_ && + new_space_.Capacity() == new_space_.MaximumCapacity() && + IsStableOrIncreasingSurvivalTrend() && + IsHighSurvivalRate()) { + // Stable high survival rates even though young generation is at + // maximum capacity indicates that most objects will be promoted. + // To decrease scavenger pauses and final mark-sweep pauses, we + // have to limit maximal capacity of the young generation. + new_space_high_promotion_mode_active_ = true; + if (FLAG_trace_gc) { + PrintF("Limited new space size due to high promotion rate: %d MB\n", + new_space_.InitialCapacity() / MB); + } + } else if (new_space_high_promotion_mode_active_ && + IsStableOrDecreasingSurvivalTrend() && + IsLowSurvivalRate()) { + // Decreasing low survival rates might indicate that the above high + // promotion mode is over and we should allow the young generation + // to grow again. + new_space_high_promotion_mode_active_ = false; + if (FLAG_trace_gc) { + PrintF("Unlimited new space size due to low promotion rate: %d MB\n", + new_space_.MaximumCapacity() / MB); + } + } + if (new_space_high_promotion_mode_active_ && new_space_.Capacity() > new_space_.InitialCapacity()) { new_space_.Shrink(); @@ -1099,7 +1105,7 @@ void Heap::Scavenge() { isolate_->descriptor_lookup_cache()->Clear(); // Used for updating survived_since_last_expansion_ at function end. - intptr_t survived_watermark = PromotedSpaceSize(); + intptr_t survived_watermark = PromotedSpaceSizeOfObjects(); CheckNewSpaceExpansionCriteria(); @@ -1191,7 +1197,7 @@ void Heap::Scavenge() { // Update how much has survived scavenge. IncrementYoungSurvivorsCounter(static_cast( - (PromotedSpaceSize() - survived_watermark) + new_space_.Size())); + (PromotedSpaceSizeOfObjects() - survived_watermark) + new_space_.Size())); LOG(isolate_, ResourceEvent("scavenge", "end")); @@ -5422,6 +5428,16 @@ intptr_t Heap::PromotedSpaceSize() { } +intptr_t Heap::PromotedSpaceSizeOfObjects() { + return old_pointer_space_->SizeOfObjects() + + old_data_space_->SizeOfObjects() + + code_space_->SizeOfObjects() + + map_space_->SizeOfObjects() + + cell_space_->SizeOfObjects() + + lo_space_->SizeOfObjects(); +} + + int Heap::PromotedExternalMemorySize() { if (amount_of_external_allocated_memory_ <= amount_of_external_allocated_memory_at_last_global_gc_) return 0; diff --git a/src/heap.h b/src/heap.h index a5ddac3f2c..c8ac927cd2 100644 --- a/src/heap.h +++ b/src/heap.h @@ -1382,6 +1382,7 @@ class Heap { void CheckNewSpaceExpansionCriteria(); inline void IncrementYoungSurvivorsCounter(int survived) { + ASSERT(survived >= 0); young_survivors_after_last_gc_ = survived; survived_since_last_expansion_ += survived; } @@ -1431,6 +1432,7 @@ class Heap { // Returns the size of objects residing in non new spaces. intptr_t PromotedSpaceSize(); + intptr_t PromotedSpaceSizeOfObjects(); double total_regexp_code_generated() { return total_regexp_code_generated_; } void IncreaseTotalRegexpCodeGenerated(int size) { @@ -1805,11 +1807,13 @@ class Heap { enum SurvivalRateTrend { INCREASING, STABLE, DECREASING, FLUCTUATING }; - static const int kYoungSurvivalRateThreshold = 90; + static const int kYoungSurvivalRateHighThreshold = 90; + static const int kYoungSurvivalRateLowThreshold = 10; static const int kYoungSurvivalRateAllowedDeviation = 15; int young_survivors_after_last_gc_; int high_survival_rate_period_length_; + int low_survival_rate_period_length_; double survival_rate_; SurvivalRateTrend previous_survival_rate_trend_; SurvivalRateTrend survival_rate_trend_; @@ -1842,18 +1846,28 @@ class Heap { } } + bool IsStableOrDecreasingSurvivalTrend() { + switch (survival_rate_trend()) { + case STABLE: + case DECREASING: + return true; + default: + return false; + } + } + bool IsIncreasingSurvivalTrend() { return survival_rate_trend() == INCREASING; } - bool IsDecreasingSurvivalTrend() { - return survival_rate_trend() == DECREASING; - } - bool IsHighSurvivalRate() { return high_survival_rate_period_length_ > 0; } + bool IsLowSurvivalRate() { + return low_survival_rate_period_length_ > 0; + } + void SelectScavengingVisitorsTable(); void StartIdleRound() {