Implement high promotion mode for new space.

This mode drastically decreases pause times by limiting maximum capacity
of the young generation when mutators generate many long-lived objects.
It shrinks new space back to the initial capacity and keeps it at that
capacity until survival rate decreases again.

R=erik.corry@gmail.com

Review URL: http://codereview.chromium.org/8702006

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10072 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent f8cabc64
...@@ -112,6 +112,7 @@ Heap::Heap() ...@@ -112,6 +112,7 @@ Heap::Heap()
disallow_allocation_failure_(false), disallow_allocation_failure_(false),
debug_utils_(NULL), debug_utils_(NULL),
#endif // DEBUG #endif // DEBUG
new_space_high_promotion_mode_active_(false),
old_gen_promotion_limit_(kMinimumPromotionLimit), old_gen_promotion_limit_(kMinimumPromotionLimit),
old_gen_allocation_limit_(kMinimumAllocationLimit), old_gen_allocation_limit_(kMinimumAllocationLimit),
old_gen_limit_factor_(1), old_gen_limit_factor_(1),
...@@ -735,6 +736,32 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, ...@@ -735,6 +736,32 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
UpdateSurvivalRateTrend(start_new_space_size); 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(); size_of_old_gen_at_last_old_space_gc_ = PromotedSpaceSize();
if (high_survival_rate_during_scavenges && if (high_survival_rate_during_scavenges &&
...@@ -764,6 +791,11 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector, ...@@ -764,6 +791,11 @@ bool Heap::PerformGarbageCollection(GarbageCollector collector,
UpdateSurvivalRateTrend(start_new_space_size); UpdateSurvivalRateTrend(start_new_space_size);
} }
if (new_space_high_promotion_mode_active_ &&
new_space_.Capacity() > new_space_.InitialCapacity()) {
new_space_.Shrink();
}
isolate_->counters()->objs_since_last_young()->Set(0); isolate_->counters()->objs_since_last_young()->Set(0);
gc_post_processing_depth_++; gc_post_processing_depth_++;
...@@ -916,9 +948,11 @@ static void VerifyNonPointerSpacePointers() { ...@@ -916,9 +948,11 @@ static void VerifyNonPointerSpacePointers() {
void Heap::CheckNewSpaceExpansionCriteria() { void Heap::CheckNewSpaceExpansionCriteria() {
if (new_space_.Capacity() < new_space_.MaximumCapacity() && if (new_space_.Capacity() < new_space_.MaximumCapacity() &&
survived_since_last_expansion_ > new_space_.Capacity()) { survived_since_last_expansion_ > new_space_.Capacity() &&
// Grow the size of new space if there is room to grow and enough !new_space_high_promotion_mode_active_) {
// data has survived scavenge since the last expansion. // Grow the size of new space if there is room to grow, enough data
// has survived scavenge since the last expansion and we are not in
// high promotion mode.
new_space_.Grow(); new_space_.Grow();
survived_since_last_expansion_ = 0; survived_since_last_expansion_ = 0;
} }
......
...@@ -1569,6 +1569,10 @@ class Heap { ...@@ -1569,6 +1569,10 @@ class Heap {
HeapDebugUtils* debug_utils_; HeapDebugUtils* debug_utils_;
#endif // DEBUG #endif // DEBUG
// Indicates that the new space should be kept small due to high promotion
// rates caused by the mutator allocating a lot of long-lived objects.
bool new_space_high_promotion_mode_active_;
// Limit that triggers a global GC on the next (normally caused) GC. This // Limit that triggers a global GC on the next (normally caused) GC. This
// is checked when we have already decided to do a GC to help determine // is checked when we have already decided to do a GC to help determine
// which collector to invoke. // which collector to invoke.
...@@ -1809,6 +1813,10 @@ class Heap { ...@@ -1809,6 +1813,10 @@ class Heap {
return survival_rate_trend() == INCREASING; return survival_rate_trend() == INCREASING;
} }
bool IsDecreasingSurvivalTrend() {
return survival_rate_trend() == DECREASING;
}
bool IsHighSurvivalRate() { bool IsHighSurvivalRate() {
return high_survival_rate_period_length_ > 0; return high_survival_rate_period_length_ > 0;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment