Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(296)

Unified Diff: src/heap/heap.cc

Issue 1161603006: Take into account freed global handles and fragmentation when computing heap growing factor. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Adjust factor Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/heap/heap.h ('K') | « src/heap/heap.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/heap/heap.cc
diff --git a/src/heap/heap.cc b/src/heap/heap.cc
index 76209c42b5ec1cd198118589b78909cf3329478a..85a5e3023f4571956539c5869c0f3531ba976689 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,24 @@ bool Heap::PerformGarbageCollection(
// Update relocatables.
Relocatable::PostGarbageCollectionProcessing(isolate_);
+ size_t total_committed = 0;
+ int fragmentation_percent =
+ FragmentationOfCompactedSpacesInPercent(&total_committed);
Hannes Payer (out of office) 2015/06/03 06:32:57 Can we have a separate function which returns tota
+ // Ignore fragmentation of non-compactable heaps and small heaps.
+ const size_t kSmallHeapThreshold = 8 * Page::kPageSize;
+ if (FLAG_never_compact || total_committed <= kSmallHeapThreshold) {
+ 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(),
+ fragmentation_percent);
+ 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 +1297,7 @@ bool Heap::PerformGarbageCollection(
}
#endif
- return freed_global_handles > 0;
+ return NextGCLikelyToFreeMore(freed_global_handles, fragmentation_percent);
}
@@ -5390,52 +5407,84 @@ intptr_t Heap::CalculateOldGenerationAllocationLimit(double factor,
}
-void Heap::SetOldGenerationAllocationLimit(
- intptr_t old_gen_size, size_t current_allocation_throughput) {
-// Allocation throughput on Android devices is typically lower than on
-// non-mobile devices.
-#if V8_OS_ANDROID
- const size_t kHighThroughput = 2500;
- const size_t kLowThroughput = 250;
-#else
- 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;
- } 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);
+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;
+
+ const size_t kPointerMultiplier = i::kPointerSize / 4;
+ // We use kHighThroughputFactor if allocation_throughput >= kHighThroughput.
+ // Otherwise, we linearly interpolate between (kLowThroughput, kMinFactor)
+ // and (kMediumThroughput, kMaxFactor).
+ const size_t kHighThroughput = 10000 * kPointerMultiplier;
+ const size_t kMediumThroughput = 5000 * kPointerMultiplier;
+ const size_t kLowThroughput = 500 * kPointerMultiplier;
+
+ const double kHighThroughputFactor = 4.0;
+ const double kHighThroughputFactorForMemoryConstrained = 2.0;
+ const double kMaxFactor = 2.0;
+ const double kMinFactor = 1.1;
+
+ if (allocation_throughput == 0) {
+ // If we have no allocation throughput estimate, we conservatively assume
+ // that it is medium.
+ allocation_throughput = kMediumThroughput;
+ }
+ double factor1 = LinearInterpolation(kLowHandles, kMaxFactor, kHighHandles,
+ kMinFactor, freed_handles);
+ double factor2 =
+ LinearInterpolation(kLowThroughput, kMinFactor, kMediumThroughput,
+ kMaxFactor, allocation_throughput);
+ double factor3 = LinearInterpolation(kLowFragmentationPercent, kMaxFactor,
+ kHighFragmentationPercent, kMinFactor,
+ fragmentation_percent);
+
Hannes Payer (out of office) 2015/06/03 06:32:57 This function needs more comments about the magic
+ double factor = (factor1 + factor2 + factor3) / 3;
+ if (allocation_throughput >= kHighThroughput && freed_handles < kLowHandles) {
+ // 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.
+ if (max_old_generation_size_ <= kMaxOldSpaceSizeMediumMemoryDevice) {
+ factor = kHighThroughputFactorForMemoryConstrained;
+ } else {
+ factor = kHighThroughputFactor;
+ }
}
if (FLAG_stress_compaction ||
mark_compact_collector()->reduce_memory_footprint_) {
- factor = min_scaling_factor;
+ factor = kMinFactor;
}
+ 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, factor);
+ }
+ 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);
« src/heap/heap.h ('K') | « src/heap/heap.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698