Change GC ergonomics to better handle heap verification.
Added a new constant kMaxConcurrentRemainingBytes which put a lower
bound on the background GC watermark. This fixes a performance issue
caused by heap verification being really slow and making it that we
were excessively scheduling back to back GCs.
Greatly increases system/test performance when heap verification is
enabled.
Change-Id: I68fa5a247c42f6c661e313c49dd3ca6be29951d4
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index fc772b1..3b129fc 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -72,6 +72,7 @@
static constexpr size_t kGcAlotInterval = KB;
// Minimum amount of remaining bytes before a concurrent GC is triggered.
static constexpr size_t kMinConcurrentRemainingBytes = 128 * KB;
+static constexpr size_t kMaxConcurrentRemainingBytes = 512 * KB;
Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max_free,
double target_utilization, size_t capacity, const std::string& image_file_name,
@@ -2167,7 +2168,7 @@
if (bytes_allocated + min_free_ <= max_allowed_footprint_) {
next_gc_type_ = collector::kGcTypeSticky;
} else {
- next_gc_type_ = collector::kGcTypePartial;
+ next_gc_type_ = have_zygote_space_ ? collector::kGcTypePartial : collector::kGcTypeFull;
}
// If we have freed enough memory, shrink the heap back down.
if (bytes_allocated + max_free_ < max_allowed_footprint_) {
@@ -2181,24 +2182,23 @@
if (concurrent_gc_) {
// Calculate when to perform the next ConcurrentGC.
// Calculate the estimated GC duration.
- double gc_duration_seconds = NsToMs(gc_duration) / 1000.0;
+ const double gc_duration_seconds = NsToMs(gc_duration) / 1000.0;
// Estimate how many remaining bytes we will have when we need to start the next GC.
size_t remaining_bytes = allocation_rate_ * gc_duration_seconds;
+ remaining_bytes = std::min(remaining_bytes, kMaxConcurrentRemainingBytes);
remaining_bytes = std::max(remaining_bytes, kMinConcurrentRemainingBytes);
if (UNLIKELY(remaining_bytes > max_allowed_footprint_)) {
// A never going to happen situation that from the estimated allocation rate we will exceed
// the applications entire footprint with the given estimated allocation rate. Schedule
- // another GC straight away.
- concurrent_start_bytes_ = bytes_allocated;
- } else {
- // Start a concurrent GC when we get close to the estimated remaining bytes. When the
- // allocation rate is very high, remaining_bytes could tell us that we should start a GC
- // right away.
- concurrent_start_bytes_ = std::max(max_allowed_footprint_ - remaining_bytes,
- bytes_allocated);
+ // another GC nearly straight away.
+ remaining_bytes = kMinConcurrentRemainingBytes;
}
- DCHECK_LE(concurrent_start_bytes_, max_allowed_footprint_);
+ DCHECK_LE(remaining_bytes, max_allowed_footprint_);
DCHECK_LE(max_allowed_footprint_, growth_limit_);
+ // Start a concurrent GC when we get close to the estimated remaining bytes. When the
+ // allocation rate is very high, remaining_bytes could tell us that we should start a GC
+ // right away.
+ concurrent_start_bytes_ = std::max(max_allowed_footprint_ - remaining_bytes, bytes_allocated);
}
}
}