Change sticky GC ergonomics to use GC throughput.

The old sticky ergonomics used partial/full GC when the bytes until
the footprint limit was < min free. This was suboptimal. The new
sticky GC ergonomics do partial/full GC when the throughput
of the current sticky GC iteration is <= mean throughput of the
partial/full GC.

Total GC time on FormulaEvaluationActions.EvaluateAndApplyChanges.
Before: 26.4s
After: 24.8s
No benchmark score change measured.

Bug: 8788501

Change-Id: I90000305e93fd492a8ef5a06ec9620d830eaf90d
diff --git a/runtime/base/logging.h b/runtime/base/logging.h
index 0fcec1f..fcec733 100644
--- a/runtime/base/logging.h
+++ b/runtime/base/logging.h
@@ -235,6 +235,28 @@
   return os;
 }
 
+template<typename T>
+class ConstDumpable {
+ public:
+  explicit ConstDumpable(const T& value) : value_(value) {
+  }
+
+  void Dump(std::ostream& os) const {
+    value_.Dump(os);
+  }
+
+ private:
+  const T& value_;
+
+  DISALLOW_COPY_AND_ASSIGN(ConstDumpable);
+};
+
+template<typename T>
+std::ostream& operator<<(std::ostream& os, const ConstDumpable<T>& rhs) {
+  rhs.Dump(os);
+  return os;
+}
+
 // Helps you use operator<< in a const char*-like context such as our various 'F' methods with
 // format strings.
 template<typename T>
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index fe18f66..c769f64 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -60,23 +60,10 @@
 void CumulativeLogger::Reset() {
   MutexLock mu(Thread::Current(), lock_);
   iterations_ = 0;
+  total_time_ = 0;
   STLDeleteElements(&histograms_);
 }
 
-uint64_t CumulativeLogger::GetTotalNs() const {
-  MutexLock mu(Thread::Current(), lock_);
-  return GetTotalTime() * kAdjust;
-}
-
-uint64_t CumulativeLogger::GetTotalTime() const {
-  MutexLock mu(Thread::Current(), lock_);
-  uint64_t total = 0;
-  for (Histogram<uint64_t>* histogram : histograms_) {
-    total += histogram->Sum();
-  }
-  return total;
-}
-
 void CumulativeLogger::AddLogger(const TimingLogger &logger) {
   MutexLock mu(Thread::Current(), lock_);
   const TimingLogger::SplitTimings& splits = logger.GetSplits();
@@ -93,7 +80,7 @@
   return iterations_;
 }
 
-void CumulativeLogger::Dump(std::ostream &os) {
+void CumulativeLogger::Dump(std::ostream &os) const {
   MutexLock mu(Thread::Current(), lock_);
   DumpHistogram(os);
 }
@@ -101,7 +88,7 @@
 void CumulativeLogger::AddPair(const std::string& label, uint64_t delta_time) {
   // Convert delta time to microseconds so that we don't overflow our counters.
   delta_time /= kAdjust;
-
+  total_time_ += delta_time;
   Histogram<uint64_t>* histogram;
   Histogram<uint64_t> dummy(label.c_str());
   auto it = histograms_.find(&dummy);
@@ -123,7 +110,7 @@
   }
 };
 
-void CumulativeLogger::DumpHistogram(std::ostream &os) {
+void CumulativeLogger::DumpHistogram(std::ostream &os) const {
   os << "Start Dumping histograms for " << iterations_ << " iterations"
      << " for " << name_ << "\n";
   std::set<Histogram<uint64_t>*, CompareHistorgramByTimeSpentDeclining>
diff --git a/runtime/base/timing_logger.h b/runtime/base/timing_logger.h
index b0bcf10..9b55898 100644
--- a/runtime/base/timing_logger.h
+++ b/runtime/base/timing_logger.h
@@ -35,8 +35,10 @@
   void Start();
   void End() LOCKS_EXCLUDED(lock_);
   void Reset() LOCKS_EXCLUDED(lock_);
-  void Dump(std::ostream& os) LOCKS_EXCLUDED(lock_);
-  uint64_t GetTotalNs() const;
+  void Dump(std::ostream& os) const LOCKS_EXCLUDED(lock_);
+  uint64_t GetTotalNs() const {
+    return GetTotalTime() * kAdjust;
+  }
   // Allow the name to be modified, particularly when the cumulative logger is a field within a
   // parent class that is unable to determine the "name" of a sub-class.
   void SetName(const std::string& name) LOCKS_EXCLUDED(lock_);
@@ -57,14 +59,17 @@
 
   void AddPair(const std::string &label, uint64_t delta_time)
       EXCLUSIVE_LOCKS_REQUIRED(lock_);
-  void DumpHistogram(std::ostream &os) EXCLUSIVE_LOCKS_REQUIRED(lock_);
-  uint64_t GetTotalTime() const;
+  void DumpHistogram(std::ostream &os) const EXCLUSIVE_LOCKS_REQUIRED(lock_);
+  uint64_t GetTotalTime() const {
+    return total_time_;
+  }
   static const uint64_t kAdjust = 1000;
   std::set<Histogram<uint64_t>*, HistogramComparator> histograms_ GUARDED_BY(lock_);
   std::string name_;
   const std::string lock_name_;
   mutable Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   size_t iterations_ GUARDED_BY(lock_);
+  uint64_t total_time_;
 
   DISALLOW_COPY_AND_ASSIGN(CumulativeLogger);
 };