Decrease target utilization for foreground apps.

GC time in FormulaEvaluationActions.EvaluateAndApplyChanges goes from
26.1s to 23.2s. Benchmark score goes down ~50 in
FormulaEvaluationActions.EvaluateAndApplyChanges, and up ~50 in
GenericCalcActions.MemAllocTest.

Bug: 8788501
Change-Id: I412af1205f8b67e70a12237c990231ea62167bc0
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index 07d0455..de7d0b8 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -88,7 +88,8 @@
 static constexpr size_t kNonMovingSpaceCapacity = 64 * MB;
 
 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,
+           double target_utilization, double foreground_heap_growth_multiplier, size_t capacity,
+           const std::string& image_file_name,
            CollectorType foreground_collector_type, CollectorType background_collector_type,
            size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode,
            size_t long_pause_log_threshold, size_t long_gc_log_threshold,
@@ -154,6 +155,7 @@
       min_free_(min_free),
       max_free_(max_free),
       target_utilization_(target_utilization),
+      foreground_heap_growth_multiplier_(foreground_heap_growth_multiplier),
       total_wait_time_(0),
       total_allocation_time_(0),
       verify_object_mode_(kVerifyObjectModeDisabled),
@@ -2524,22 +2526,33 @@
   return nullptr;
 }
 
+double Heap::HeapGrowthMultiplier() const {
+  // If we don't care about pause times we are background, so return 1.0.
+  if (!CareAboutPauseTimes() || IsLowMemoryMode()) {
+    return 1.0;
+  }
+  return foreground_heap_growth_multiplier_;
+}
+
 void Heap::GrowForUtilization(collector::GarbageCollector* collector_ran) {
   // We know what our utilization is at this moment.
   // This doesn't actually resize any memory. It just lets the heap grow more when necessary.
-  const size_t bytes_allocated = GetBytesAllocated();
+  const uint64_t bytes_allocated = GetBytesAllocated();
   last_gc_size_ = bytes_allocated;
   last_gc_time_ns_ = NanoTime();
-  size_t target_size;
+  uint64_t target_size;
   collector::GcType gc_type = collector_ran->GetGcType();
   if (gc_type != collector::kGcTypeSticky) {
     // Grow the heap for non sticky GC.
-    target_size = bytes_allocated / GetTargetHeapUtilization();
-    if (target_size > bytes_allocated + max_free_) {
-      target_size = bytes_allocated + max_free_;
-    } else if (target_size < bytes_allocated + min_free_) {
-      target_size = bytes_allocated + min_free_;
-    }
+    const float multiplier = HeapGrowthMultiplier();  // Use the multiplier to grow more for
+    // foreground.
+    intptr_t delta = bytes_allocated / GetTargetHeapUtilization() - bytes_allocated;
+    CHECK_GE(delta, 0);
+    target_size = bytes_allocated + delta * multiplier;
+    target_size = std::min(target_size,
+                           bytes_allocated + static_cast<uint64_t>(max_free_ * multiplier));
+    target_size = std::max(target_size,
+                           bytes_allocated + static_cast<uint64_t>(min_free_ * multiplier));
     native_need_to_run_finalization_ = true;
     next_gc_type_ = collector::kGcTypeSticky;
   } else {
@@ -2564,7 +2577,7 @@
     if (bytes_allocated + max_free_ < max_allowed_footprint_) {
       target_size = bytes_allocated + max_free_;
     } else {
-      target_size = std::max(bytes_allocated, max_allowed_footprint_);
+      target_size = std::max(bytes_allocated, static_cast<uint64_t>(max_allowed_footprint_));
     }
   }
   if (!ignore_max_footprint_) {
@@ -2588,7 +2601,8 @@
       // 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);
+      concurrent_start_bytes_ = std::max(max_allowed_footprint_ - remaining_bytes,
+                                         static_cast<size_t>(bytes_allocated));
     }
   }
 }
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 874357f..35724e3 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -132,9 +132,8 @@
   static constexpr size_t kDefaultLongPauseLogThreshold = MsToNs(5);
   static constexpr size_t kDefaultLongGCLogThreshold = MsToNs(100);
   static constexpr size_t kDefaultTLABSize = 256 * KB;
-
-  // Default target utilization.
   static constexpr double kDefaultTargetUtilization = 0.5;
+  static constexpr double kDefaultHeapGrowthMultiplier = 2.0;
 
   // Used so that we don't overflow the allocation time atomic integer.
   static constexpr size_t kTimeAdjust = 1024;
@@ -148,7 +147,8 @@
   // image_file_names names specify Spaces to load based on
   // ImageWriter output.
   explicit Heap(size_t initial_size, size_t growth_limit, size_t min_free,
-                size_t max_free, double target_utilization, size_t capacity,
+                size_t max_free, double target_utilization,
+                double foreground_heap_growth_multiplier, size_t capacity,
                 const std::string& original_image_file_name,
                 CollectorType foreground_collector_type, CollectorType background_collector_type,
                 size_t parallel_gc_threads, size_t conc_gc_threads, bool low_memory_mode,
@@ -351,6 +351,10 @@
     return low_memory_mode_;
   }
 
+  // Returns the heap growth multiplier, this affects how much we grow the heap after a GC.
+  // Scales heap growth, min free, and max free.
+  double HeapGrowthMultiplier() const;
+
   // Freed bytes can be negative in cases where we copy objects from a compacted space to a
   // free-list backed space.
   void RecordFree(ssize_t freed_objects, ssize_t freed_bytes);
@@ -927,6 +931,9 @@
   // Target ideal heap utilization ratio
   double target_utilization_;
 
+  // How much more we grow the heap when we are a foreground app instead of background.
+  double foreground_heap_growth_multiplier_;
+
   // Total time which mutators are paused or waiting for GC to complete.
   uint64_t total_wait_time_;
 
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 29fe536..57d32bb 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -131,6 +131,7 @@
   heap_min_free_ = gc::Heap::kDefaultMinFree;
   heap_max_free_ = gc::Heap::kDefaultMaxFree;
   heap_target_utilization_ = gc::Heap::kDefaultTargetUtilization;
+  foreground_heap_growth_multiplier_ = gc::Heap::kDefaultHeapGrowthMultiplier;
   heap_growth_limit_ = 0;  // 0 means no growth limit .
   // Default to number of processors minus one since the main GC thread also does work.
   parallel_gc_threads_ = sysconf(_SC_NPROCESSORS_CONF) - 1;
@@ -314,6 +315,10 @@
       if (!ParseDouble(option, '=', 0.1, 0.9, &heap_target_utilization_)) {
         return false;
       }
+    } else if (StartsWith(option, "-XX:ForegroundHeapGrowthMultiplier=")) {
+      if (!ParseDouble(option, '=', 0.1, 0.9, &foreground_heap_growth_multiplier_)) {
+        return false;
+      }
     } else if (StartsWith(option, "-XX:ParallelGCThreads=")) {
       if (!ParseUnsignedInteger(option, '=', &parallel_gc_threads_)) {
         return false;
diff --git a/runtime/parsed_options.h b/runtime/parsed_options.h
index 126096a..770e4ae 100644
--- a/runtime/parsed_options.h
+++ b/runtime/parsed_options.h
@@ -54,6 +54,7 @@
   size_t heap_min_free_;
   size_t heap_max_free_;
   double heap_target_utilization_;
+  double foreground_heap_growth_multiplier_;
   unsigned int parallel_gc_threads_;
   unsigned int conc_gc_threads_;
   gc::CollectorType collector_type_;
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 5c31d35..eb0522a 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -564,6 +564,7 @@
                        options->heap_min_free_,
                        options->heap_max_free_,
                        options->heap_target_utilization_,
+                       options->foreground_heap_growth_multiplier_,
                        options->heap_maximum_size_,
                        options->image_,
                        options->collector_type_,