Index: src/heap/heap.cc |
diff --git a/src/heap/heap.cc b/src/heap/heap.cc |
index 76209c42b5ec1cd198118589b78909cf3329478a..6e551e433f22b4b7d673f225638d9b8344f3cdea 100644 |
--- a/src/heap/heap.cc |
+++ b/src/heap/heap.cc |
@@ -1218,6 +1218,12 @@ bool Heap::PerformGarbageCollection( |
// Perform mark-sweep with optional compaction. |
MarkCompact(); |
sweep_generation_++; |
+ // Temporarily set the limit for case when PostGarbageCollectionProcessing |
+ // allocates and triggers GC. The real limit is set at after |
+ // PostGarbageCollectionProcessing. |
+ const double kConservativeFactor = 1.5; |
+ SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), |
+ kConservativeFactor); |
old_gen_exhausted_ = false; |
old_generation_size_configured_ = true; |
} else { |
@@ -1251,13 +1257,17 @@ bool Heap::PerformGarbageCollection( |
// Update relocatables. |
Relocatable::PostGarbageCollectionProcessing(isolate_); |
+ int fragmentation_percent = 0; |
+ |
if (collector == MARK_COMPACTOR) { |
// Register the amount of external allocated memory. |
amount_of_external_allocated_memory_at_last_global_gc_ = |
amount_of_external_allocated_memory_; |
- SetOldGenerationAllocationLimit( |
- PromotedSpaceSizeOfObjects(), |
- tracer()->CurrentAllocationThroughputInBytesPerMillisecond()); |
+ double factor = HeapGrowingFactor( |
+ freed_global_handles, |
+ tracer()->CurrentAllocationThroughputInBytesPerMillisecond(), |
+ FragmentationOfCompactedSpacesInPercent()); |
+ SetOldGenerationAllocationLimit(PromotedSpaceSizeOfObjects(), factor); |
// We finished a marking cycle. We can uncommit the marking deque until |
// we start marking again. |
mark_compact_collector_.UncommitMarkingDeque(); |
@@ -1280,7 +1290,8 @@ bool Heap::PerformGarbageCollection( |
} |
#endif |
- return freed_global_handles > 0; |
+ return freed_global_handles > 0 || |
+ fragmentation_percent >= kLowFragmentationPercent; |
Hannes Payer (out of office)
2015/06/02 08:23:00
Can we move this code into a function with a descr
ulan
2015/06/02 12:27:05
Done.
|
} |
@@ -5390,8 +5401,19 @@ intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor, |
} |
-void Heap::SetOldGenerationAllocationLimit( |
- intptr_t old_gen_size, size_t current_allocation_throughput) { |
+double LinearInterpolation(double x1, double y1, double x2, double y2, |
+ double x) { |
+ DCHECK(x1 < x2); |
+ if (x <= x1) return y1; |
+ if (x >= x2) return y2; |
+ return y1 + (y2 - y1) / (x2 - x1) * (x - x1); |
+} |
+ |
+ |
+double Heap::HeapGrowingFactor(int freed_handles, size_t allocation_throughput, |
+ int fragmentation_percent) { |
+ const int kLowHandles = 100; |
+ const int kHighHandles = 1000; |
// Allocation throughput on Android devices is typically lower than on |
// non-mobile devices. |
#if V8_OS_ANDROID |
@@ -5401,41 +5423,59 @@ void Heap::SetOldGenerationAllocationLimit( |
const size_t kHighThroughput = 10000; |
const size_t kLowThroughput = 1000; |
#endif |
- const double min_scaling_factor = 1.1; |
- const double max_scaling_factor = 1.5; |
- double max_factor = 4; |
- const double idle_max_factor = 1.5; |
- // We set the old generation growing factor to 2 to grow the heap slower on |
- // memory-constrained devices. |
- if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) { |
- max_factor = 2; |
- } |
- |
- double factor; |
- double idle_factor; |
- if (current_allocation_throughput == 0 || |
- current_allocation_throughput >= kHighThroughput) { |
- factor = max_factor; |
- } else if (current_allocation_throughput <= kLowThroughput) { |
- factor = min_scaling_factor; |
+ const double min_factor = 1.1; |
+ const double max_factor = 1.5; |
+ if (allocation_throughput == 0) { |
+ // If we have no allocation throughput estimate, we conservatively assume |
+ // that it is high. |
+ allocation_throughput = kHighThroughput; |
+ } |
+ double factor1 = LinearInterpolation(kLowHandles, max_factor, kHighHandles, |
+ min_factor, freed_handles); |
+ double factor2 = |
+ LinearInterpolation(kLowThroughput, min_factor, kHighThroughput, |
+ max_factor, allocation_throughput); |
+ double factor3 = LinearInterpolation(kLowFragmentationPercent, max_factor, |
+ kHighFragmentationPercent, min_factor, |
+ fragmentation_percent); |
+ |
+ double factor = Min(factor1, factor2); |
+ if (factor >= max_factor) { |
+ // We need high throughput, schedule GC late. |
+ // We set the old generation growing factor to 2 to grow the heap slower on |
+ // memory-constrained devices. |
+ factor = (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) |
+ ? 2 |
Hannes Payer (out of office)
2015/06/02 08:23:00
Let's make these two value also constants.
ulan
2015/06/02 12:27:05
Done.
|
+ : 4; |
} else { |
- // Compute factor using linear interpolation between points |
- // (kHighThroughput, max_scaling_factor) and (kLowThroughput, min_factor). |
- factor = min_scaling_factor + |
- (current_allocation_throughput - kLowThroughput) * |
- (max_scaling_factor - min_scaling_factor) / |
- (kHighThroughput - kLowThroughput); |
+ factor = Min(factor, factor3); |
} |
if (FLAG_stress_compaction || |
mark_compact_collector()->reduce_memory_footprint_) { |
- factor = min_scaling_factor; |
+ factor = min_factor; |
+ } |
+ |
+ if (FLAG_trace_gc_verbose) { |
+ PrintIsolate(isolate_, |
+ "Freed handles: %d (factor %.1f)," |
+ "allocation throughput: %u (factor %.1f)," |
+ "fragmentation: %d (factor %.1f), combined factor: %.1f\n", |
+ freed_handles, factor1, allocation_throughput, factor2, |
+ fragmentation_percent, factor3); |
} |
+ return factor; |
+} |
+ |
+ |
+void Heap::SetOldGenerationAllocationLimit(intptr_t old_gen_size, |
+ double factor) { |
+ const double idle_max_factor = 1.5; |
// TODO(hpayer): Investigate if idle_old_generation_allocation_limit_ is still |
// needed after taking the allocation rate for the old generation limit into |
// account. |
- idle_factor = Min(factor, idle_max_factor); |
+ const double idle_factor = Min(factor, idle_max_factor); |
old_generation_allocation_limit_ = |
CalculateOldGenerationAllocationLimit(factor, old_gen_size); |