am e5426c99: Fix histogram memory issues.

* commit 'e5426c9995d28bcb19391d8dbf0ad70606cf1770':
  Fix histogram memory issues.
diff --git a/runtime/base/histogram-inl.h b/runtime/base/histogram-inl.h
index 1a63cf4..0345266 100644
--- a/runtime/base/histogram-inl.h
+++ b/runtime/base/histogram-inl.h
@@ -29,7 +29,7 @@
 namespace art {
 
 template <class Value> inline void Histogram<Value>::AddValue(Value value) {
-  CHECK_GE(value, 0.0);
+  CHECK_GE(value, static_cast<Value>(0));
   if (value >= max_) {
     Value new_max = ((value + 1) / bucket_width_ + 1) * bucket_width_;
     DCHECK_GT(new_max, max_);
@@ -37,91 +37,90 @@
   }
 
   BucketiseValue(value);
-  new_values_added_ = true;
 }
 
 template <class Value>
-inline Histogram<Value>::Histogram(const std::string name)
+inline Histogram<Value>::Histogram(const char* name, Value initial_bucket_width,
+                                   size_t max_buckets)
     : kAdjust(1000),
-      kBucketWidth(5),
-      kInitialBucketCount(10),
-      bucket_width_(kBucketWidth),
-      bucket_count_(kInitialBucketCount) {
-  name_ = name;
+      kInitialBucketCount(8),
+      name_(name),
+      max_buckets_(max_buckets),
+      bucket_width_(initial_bucket_width) {
   Reset();
 }
 
 template <class Value>
 inline void Histogram<Value>::GrowBuckets(Value new_max) {
   while (max_ < new_max) {
+    // If we have reached the maximum number of buckets, merge buckets together.
+    if (frequency_.size() >= max_buckets_) {
+      CHECK(IsAligned<2>(frequency_.size()));
+      // We double the width of each bucket to reduce the number of buckets by a factor of 2.
+      bucket_width_ *= 2;
+      const size_t limit = frequency_.size() / 2;
+      // Merge the frequencies by adding each adjacent two together.
+      for (size_t i = 0; i < limit; ++i) {
+        frequency_[i] = frequency_[i * 2] + frequency_[i * 2 + 1];
+      }
+      // Remove frequencies in the second half of the array which were added to the first half.
+      while (frequency_.size() > limit) {
+        frequency_.pop_back();
+      }
+    }
     max_ += bucket_width_;
-    ranges_.push_back(max_);
     frequency_.push_back(0);
-    bucket_count_++;
   }
 }
 
-template <class Value> inline size_t Histogram<Value>::FindBucket(Value val) {
+template <class Value> inline size_t Histogram<Value>::FindBucket(Value val) const {
   // Since this is only a linear histogram, bucket index can be found simply with
   // dividing the value by the bucket width.
   DCHECK_GE(val, min_);
   DCHECK_LE(val, max_);
-  size_t bucket_idx = static_cast<size_t>(static_cast<double>(val - min_) / bucket_width_);
+  const size_t bucket_idx = static_cast<size_t>((val - min_) / bucket_width_);
   DCHECK_GE(bucket_idx, 0ul);
-  DCHECK_LE(bucket_idx, bucket_count_);
+  DCHECK_LE(bucket_idx, GetBucketCount());
   return bucket_idx;
 }
 
 template <class Value>
-inline void Histogram<Value>::BucketiseValue(Value value) {
-  CHECK_LT(value, max_);
-  sum_ += value;
-  sum_of_squares_ += value * value;
-  size_t bucket_idx = FindBucket(value);
-  sample_size_++;
-  if (value > max_value_added_) {
-    max_value_added_ = value;
-  }
-  if (value < min_value_added_) {
-    min_value_added_ = value;
-  }
-  frequency_[bucket_idx]++;
+inline void Histogram<Value>::BucketiseValue(Value val) {
+  CHECK_LT(val, max_);
+  sum_ += val;
+  sum_of_squares_ += val * val;
+  ++sample_size_;
+  ++frequency_[FindBucket(val)];
+  max_value_added_ = std::max(val, max_value_added_);
+  min_value_added_ = std::min(val, min_value_added_);
 }
 
 template <class Value> inline void Histogram<Value>::Initialize() {
-  DCHECK_GT(bucket_count_, 0ul);
-  size_t idx = 0;
-  for (; idx < bucket_count_; idx++) {
-    ranges_.push_back(min_ + static_cast<Value>(idx) * (bucket_width_));
+  for (size_t idx = 0; idx < kInitialBucketCount; idx++) {
     frequency_.push_back(0);
   }
   // Cumulative frequency and ranges has a length of 1 over frequency.
-  ranges_.push_back(min_ + idx * bucket_width_);
-  max_ = bucket_width_ * bucket_count_;
+  max_ = bucket_width_ * GetBucketCount();
+}
+
+template <class Value> inline size_t Histogram<Value>::GetBucketCount() const {
+  return frequency_.size();
 }
 
 template <class Value> inline void Histogram<Value>::Reset() {
-  bucket_width_ = kBucketWidth;
-  bucket_count_ = kInitialBucketCount;
-  max_ = bucket_width_ * bucket_count_;
   sum_of_squares_ = 0;
   sample_size_ = 0;
   min_ = 0;
   sum_ = 0;
   min_value_added_ = std::numeric_limits<Value>::max();
   max_value_added_ = std::numeric_limits<Value>::min();
-  new_values_added_ = false;
-  ranges_.clear();
   frequency_.clear();
-  cumulative_freq_.clear();
-  cumulative_perc_.clear();
   Initialize();
 }
 
-template <class Value> inline void Histogram<Value>::BuildRanges() {
-  for (size_t idx = 0; idx < bucket_count_; ++idx) {
-    ranges_.push_back(min_ + idx * bucket_width_);
-  }
+template <class Value> inline Value Histogram<Value>::GetRange(size_t bucket_idx) const {
+  DCHECK_LE(bucket_idx, GetBucketCount());
+  return min_ + bucket_idx * bucket_width_;
 }
 
 template <class Value> inline double Histogram<Value>::Mean() const {
@@ -143,25 +142,21 @@
 }
 
 template <class Value>
-inline void Histogram<Value>::PrintBins(std::ostream &os) {
+inline void Histogram<Value>::PrintBins(std::ostream& os, const CumulativeData& data) const {
   DCHECK_GT(sample_size_, 0ull);
-  DCHECK(!new_values_added_);
-  size_t bin_idx = 0;
-  while (bin_idx < cumulative_freq_.size()) {
-    if (bin_idx > 0 &&
-        cumulative_perc_[bin_idx] == cumulative_perc_[bin_idx - 1]) {
+  for (size_t bin_idx = 0; bin_idx < data.freq_.size(); ++bin_idx) {
+    if (bin_idx > 0 && data.perc_[bin_idx] == data.perc_[bin_idx - 1]) {
       bin_idx++;
       continue;
     }
-    os << ranges_[bin_idx] << ": " << cumulative_freq_[bin_idx] << "\t"
-       << cumulative_perc_[bin_idx] * 100.0 << "%\n";
-    bin_idx++;
+    os << GetRange(bin_idx) << ": " << data.freq_[bin_idx] << "\t"
+       << data.perc_[bin_idx] * 100.0 << "%\n";
   }
 }
 
 template <class Value>
-inline void Histogram<Value>::PrintConfidenceIntervals(std::ostream &os,
-                                                       double interval) const {
+inline void Histogram<Value>::PrintConfidenceIntervals(std::ostream &os, double interval,
+                                                       const CumulativeData& data) const {
   DCHECK_GT(interval, 0);
   DCHECK_LT(interval, 1.0);
 
@@ -169,69 +164,51 @@
   double per_1 = per_0 + interval;
   os << Name() << ":\t";
   TimeUnit unit = GetAppropriateTimeUnit(Mean() * kAdjust);
-  os << (interval * 100) << "% C.I. "
-     << FormatDuration(Percentile(per_0) * kAdjust, unit);
-  os << "-" << FormatDuration(Percentile(per_1) * kAdjust, unit) << " ";
+  os << (interval * 100) << "% C.I. " << FormatDuration(Percentile(per_0, data) * kAdjust, unit);
+  os << "-" << FormatDuration(Percentile(per_1, data) * kAdjust, unit) << " ";
   os << "Avg: " << FormatDuration(Mean() * kAdjust, unit) << " Max: ";
   os << FormatDuration(Max() * kAdjust, unit) << "\n";
 }
 
-template <class Value> inline void Histogram<Value>::BuildCDF() {
-  DCHECK_EQ(cumulative_freq_.size(), 0ull);
-  DCHECK_EQ(cumulative_perc_.size(), 0ull);
+template <class Value> inline void Histogram<Value>::CreateHistogram(CumulativeData& out_data) {
+  DCHECK_GT(sample_size_, 0ull);
+  out_data.freq_.clear();
+  out_data.perc_.clear();
   uint64_t accumulated = 0;
-
-  cumulative_freq_.push_back(accumulated);
-  cumulative_perc_.push_back(0.0);
+  out_data.freq_.push_back(accumulated);
+  out_data.perc_.push_back(0.0);
   for (size_t idx = 0; idx < frequency_.size(); idx++) {
     accumulated += frequency_[idx];
-    cumulative_freq_.push_back(accumulated);
-    cumulative_perc_.push_back(static_cast<double>(accumulated) /
-                               static_cast<double>(sample_size_));
+    out_data.freq_.push_back(accumulated);
+    out_data.perc_.push_back(static_cast<double>(accumulated) / static_cast<double>(sample_size_));
   }
-  DCHECK_EQ(*(cumulative_freq_.end() - 1), sample_size_);
-  DCHECK_EQ(*(cumulative_perc_.end() - 1), 1.0);
-}
-
-template <class Value> inline void Histogram<Value>::CreateHistogram() {
-  DCHECK_GT(sample_size_, 0ull);
-
-  // Create a histogram only if new values are added.
-  if (!new_values_added_)
-    return;
-
-  // Reset cumulative values in case this is not the first time creating histogram.
-  cumulative_freq_.clear();
-  cumulative_perc_.clear();
-  BuildCDF();
-  new_values_added_ = false;
+  DCHECK_EQ(out_data.freq_.back(), sample_size_);
+  DCHECK_LE(std::abs(out_data.perc_.back() - 1.0), 0.001);
 }
 
 template <class Value>
-inline double Histogram<Value>::Percentile(double per) const {
-  DCHECK_GT(cumulative_perc_.size(), 0ull);
-  size_t idx, upper_idx = 0, lower_idx = 0;
-  for (idx = 0; idx < cumulative_perc_.size(); idx++) {
-    if (per <= cumulative_perc_[idx]) {
+inline double Histogram<Value>::Percentile(double per, const CumulativeData& data) const {
+  DCHECK_GT(data.perc_.size(), 0ull);
+  size_t upper_idx = 0, lower_idx = 0;
+  for (size_t idx = 0; idx < data.perc_.size(); idx++) {
+    if (per <= data.perc_[idx]) {
       upper_idx = idx;
       break;
     }
 
-    if (per >= cumulative_perc_[idx] && idx != 0 &&
-        cumulative_perc_[idx] != cumulative_perc_[idx - 1]) {
+    if (per >= data.perc_[idx] && idx != 0 && data.perc_[idx] != data.perc_[idx - 1]) {
       lower_idx = idx;
     }
   }
 
-  double upper_value = static_cast<double>(ranges_[upper_idx]);
-  double lower_value = static_cast<double>(ranges_[lower_idx]);
-
-  double lower_perc = cumulative_perc_[lower_idx];
-  double upper_perc = cumulative_perc_[upper_idx];
-
+  const double lower_perc = data.perc_[lower_idx];
+  const double lower_value = static_cast<double>(GetRange(lower_idx));
   if (per == lower_perc) {
     return lower_value;
   }
+
+  const double upper_perc = data.perc_[upper_idx];
+  const double upper_value = static_cast<double>(GetRange(upper_idx));
   if (per == upper_perc) {
     return upper_value;
   }
diff --git a/runtime/base/histogram.h b/runtime/base/histogram.h
index 33a1e65..f508af9 100644
--- a/runtime/base/histogram.h
+++ b/runtime/base/histogram.h
@@ -31,19 +31,33 @@
 
 template <class Value> class Histogram {
   const double kAdjust;
-  const Value kBucketWidth;
   const size_t kInitialBucketCount;
 
  public:
-  explicit Histogram(std::string);
+  class CumulativeData {
+    friend class Histogram<Value>;
+    std::vector<uint64_t> freq_;
+    std::vector<double> perc_;
+  };
+
+  Histogram(const char* name, Value initial_bucket_width, size_t max_buckets = 100);
   void AddValue(Value);
-  void CreateHistogram();
+  // Builds the cumulative distribution function from the frequency data.
+  // Accumulative summation of frequencies.
+  // cumulative_freq[i] = sum(frequency[j] : 0 < j < i )
+  // Accumulative summation of percentiles; which is the frequency / SampleSize
+  // cumulative_perc[i] = sum(frequency[j] / SampleSize : 0 < j < i )
+  void CreateHistogram(CumulativeData& data);
+  // Reset the cumulative values, next time CreateHistogram is called it will recreate the cache.
   void Reset();
   double Mean() const;
   double Variance() const;
-  double Percentile(double) const;
-  void PrintConfidenceIntervals(std::ostream &, double) const;
-  void PrintBins(std::ostream &);
+  double Percentile(double per, const CumulativeData& data) const;
+  void PrintConfidenceIntervals(std::ostream& os, double interval,
+                                const CumulativeData& data) const;
+  void PrintBins(std::ostream& os, const CumulativeData& data) const;
+  Value GetRange(size_t bucket_idx) const;
+  size_t GetBucketCount() const;
 
   uint64_t SampleSize() const {
     return sample_size_;
@@ -61,49 +75,33 @@
     return max_value_added_;
   }
 
-  const std::string &Name() const {
+  const std::string& Name() const {
     return name_;
   }
 
-
  private:
-  void BuildRanges();
   void Initialize();
-  size_t FindBucket(Value);
-  void BucketiseValue(Value);
-  // Builds the cumulative distribution function from the frequency data.
-  // Must be called before using the percentile function.
-  void BuildCDF();
+  size_t FindBucket(Value val) const;
+  void BucketiseValue(Value val);
   // Add more buckets to the histogram to fill in a new value that exceeded
   // the max_read_value_.
-  void GrowBuckets(Value);
-  bool new_values_added_;
+  void GrowBuckets(Value val);
   std::string name_;
+  // Maximum number of buckets.
+  const size_t max_buckets_;
   // Number of samples placed in histogram.
-  uint64_t sample_size_;
+  size_t sample_size_;
   // Width of the bucket range. The lower the value is the more accurate
-  // histogram percentiles are.
+  // histogram percentiles are. Grows adaptively when we hit max buckets.
   Value bucket_width_;
-  // Number of bucket to have in the histogram. this value will increase
-  // to accommodate for big values that don't fit in initial bucket ranges.
-  size_t bucket_count_;
-  // Represents the ranges of the histograms. Has SampleSize() + 1 elements
-  // e.g. 0,5,10,15 represents ranges 0-5, 5-10, 10-15
-  std::vector<Value> ranges_;
-  // How many occurrences of values fall within a corresponding range that is
-  // saved in the ranges_ vector.
-  std::vector<uint64_t> frequency_;
-  // Accumulative summation of frequencies.
-  // cumulative_freq_[i] = sum(cumulative_freq_[j] : 0 < j < i )
-  std::vector<uint64_t> cumulative_freq_;
-  // Accumulative summation of percentiles; which is the frequency / SampleSize
-  // cumulative_freq_[i] = sum(cumulative_freq_[j] : 0 < j < i )
-  std::vector<double> cumulative_perc_;
+  // How many occurrences of values fall within a bucket at index i where i covers the range
+  // starting at  min_ + i * bucket_width_ with size bucket_size_.
+  std::vector<uint32_t> frequency_;
   // Summation of all the elements inputed by the user.
   Value sum_;
-  // Maximum value that can fit in the histogram, grows adaptively.
-  Value min_;
   // Minimum value that can fit in the histogram. Fixed to zero for now.
+  Value min_;
+  // Maximum value that can fit in the histogram, grows adaptively.
   Value max_;
   // Summation of the values entered. Used to calculate variance.
   Value sum_of_squares_;
diff --git a/runtime/base/histogram_test.cc b/runtime/base/histogram_test.cc
index 218c022..534440c 100644
--- a/runtime/base/histogram_test.cc
+++ b/runtime/base/histogram_test.cc
@@ -23,7 +23,7 @@
 namespace art {
 
 // Simple usage:
-//   Histogram *hist = new Histogram("SimplePercentiles");
+//   Histogram *hist(new Histogram("SimplePercentiles"));
 //   Percentile PerValue
 //   hist->AddValue(121);
 //   hist->AddValue(132);
@@ -34,7 +34,7 @@
 //   PerValue = hist->PercentileVal(0.50); finds the 50th percentile(median).
 
 TEST(Histtest, MeanTest) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("MeanTest"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("MeanTest", 5));
 
   double mean;
   for (size_t Idx = 0; Idx < 90; Idx++) {
@@ -52,20 +52,20 @@
 }
 
 TEST(Histtest, VarianceTest) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("VarianceTest"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("VarianceTest", 5));
 
   double variance;
   hist->AddValue(9);
   hist->AddValue(17);
   hist->AddValue(28);
   hist->AddValue(28);
-  hist->CreateHistogram();
   variance = hist->Variance();
   EXPECT_EQ(64.25, variance);
 }
 
 TEST(Histtest, Percentile) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("Percentile"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("Percentile", 5));
+  Histogram<uint64_t>::CumulativeData data;
 
   double PerValue;
 
@@ -85,13 +85,14 @@
   hist->AddValue(145);
   hist->AddValue(155);
 
-  hist->CreateHistogram();
-  PerValue = hist->Percentile(0.50);
+  hist->CreateHistogram(data);
+  PerValue = hist->Percentile(0.50, data);
   EXPECT_EQ(875, static_cast<int>(PerValue * 10));
 }
 
 TEST(Histtest, UpdateRange) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("UpdateRange"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("UpdateRange", 5));
+  Histogram<uint64_t>::CumulativeData data;
 
   double PerValue;
 
@@ -116,14 +117,13 @@
   hist->AddValue(200);
   hist->AddValue(205);
   hist->AddValue(212);
-  hist->CreateHistogram();
-  PerValue = hist->Percentile(0.50);
+  hist->CreateHistogram(data);
+  PerValue = hist->Percentile(0.50, data);
 
   std::string text;
   std::stringstream stream;
-  std::string expected =
-      "UpdateRange:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
-  hist->PrintConfidenceIntervals(stream, 0.99);
+  std::string expected("UpdateRange:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n");
+  hist->PrintConfidenceIntervals(stream, 0.99, data);
 
   EXPECT_EQ(expected, stream.str());
   EXPECT_GE(PerValue, 132);
@@ -131,7 +131,8 @@
 }
 
 TEST(Histtest, Reset) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("Reset"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("Reset", 5));
+  Histogram<uint64_t>::CumulativeData data;
 
   double PerValue;
   hist->AddValue(0);
@@ -159,14 +160,13 @@
   hist->AddValue(200);
   hist->AddValue(205);
   hist->AddValue(212);
-  hist->CreateHistogram();
-  PerValue = hist->Percentile(0.50);
+  hist->CreateHistogram(data);
+  PerValue = hist->Percentile(0.50, data);
 
   std::string text;
   std::stringstream stream;
-  std::string expected =
-      "Reset:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
-  hist->PrintConfidenceIntervals(stream, 0.99);
+  std::string expected("Reset:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n");
+  hist->PrintConfidenceIntervals(stream, 0.99, data);
 
   EXPECT_EQ(expected, stream.str());
   EXPECT_GE(PerValue, 132);
@@ -174,7 +174,8 @@
 }
 
 TEST(Histtest, MultipleCreateHist) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("MultipleCreateHist"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("MultipleCreateHist", 5));
+  Histogram<uint64_t>::CumulativeData data;
 
   double PerValue;
   hist->AddValue(15);
@@ -184,7 +185,7 @@
   hist->AddValue(68);
   hist->AddValue(75);
   hist->AddValue(93);
-  hist->CreateHistogram();
+  hist->CreateHistogram(data);
   hist->AddValue(110);
   hist->AddValue(121);
   hist->AddValue(132);
@@ -193,19 +194,18 @@
   hist->AddValue(155);
   hist->AddValue(163);
   hist->AddValue(168);
-  hist->CreateHistogram();
+  hist->CreateHistogram(data);
   hist->AddValue(175);
   hist->AddValue(182);
   hist->AddValue(193);
   hist->AddValue(200);
   hist->AddValue(205);
   hist->AddValue(212);
-  hist->CreateHistogram();
-  PerValue = hist->Percentile(0.50);
+  hist->CreateHistogram(data);
+  PerValue = hist->Percentile(0.50, data);
   std::stringstream stream;
-  std::string expected =
-      "MultipleCreateHist:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n";
-  hist->PrintConfidenceIntervals(stream, 0.99);
+  std::string expected("MultipleCreateHist:\t99% C.I. 15us-212us Avg: 126.380us Max: 212us\n");
+  hist->PrintConfidenceIntervals(stream, 0.99, data);
 
   EXPECT_EQ(expected, stream.str());
   EXPECT_GE(PerValue, 132);
@@ -213,18 +213,20 @@
 }
 
 TEST(Histtest, SingleValue) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("SingleValue"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("SingleValue", 5));
+  Histogram<uint64_t>::CumulativeData data;
 
   hist->AddValue(1);
-  hist->CreateHistogram();
+  hist->CreateHistogram(data);
   std::stringstream stream;
   std::string expected = "SingleValue:\t99% C.I. 1us-1us Avg: 1us Max: 1us\n";
-  hist->PrintConfidenceIntervals(stream, 0.99);
+  hist->PrintConfidenceIntervals(stream, 0.99, data);
   EXPECT_EQ(expected, stream.str());
 }
 
 TEST(Histtest, CappingPercentiles) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("CappingPercentiles"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("CappingPercentiles", 5));
+  Histogram<uint64_t>::CumulativeData data;
 
   double per_995;
   double per_005;
@@ -232,8 +234,8 @@
   for (uint64_t idx = 0ull; idx < 150ull; idx++) {
     hist->AddValue(0);
   }
-  hist->CreateHistogram();
-  per_995 = hist->Percentile(0.995);
+  hist->CreateHistogram(data);
+  per_995 = hist->Percentile(0.995, data);
   EXPECT_EQ(per_995, 0);
   hist->Reset();
   for (size_t idx = 0; idx < 200; idx++) {
@@ -241,15 +243,16 @@
       hist->AddValue(val);
     }
   }
-  hist->CreateHistogram();
-  per_005 = hist->Percentile(0.005);
-  per_995 = hist->Percentile(0.995);
+  hist->CreateHistogram(data);
+  per_005 = hist->Percentile(0.005, data);
+  per_995 = hist->Percentile(0.995, data);
   EXPECT_EQ(1, per_005);
   EXPECT_EQ(4, per_995);
 }
 
 TEST(Histtest, SpikyValues) {
-  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("SpikyValues"));
+  UniquePtr<Histogram<uint64_t> > hist(new Histogram<uint64_t>("SpikyValues", 5, 4096));
+  Histogram<uint64_t>::CumulativeData data;
 
   for (uint64_t idx = 0ull; idx < 30ull; idx++) {
     for (uint64_t idx_inner = 0ull; idx_inner < 5ull; idx_inner++) {
@@ -257,11 +260,10 @@
     }
   }
   hist->AddValue(10000);
-  hist->CreateHistogram();
+  hist->CreateHistogram(data);
   std::stringstream stream;
-  std::string expected =
-      "SpikyValues:\t99% C.I. 0.089us-2541.825us Avg: 95.033us Max: 10000us\n";
-  hist->PrintConfidenceIntervals(stream, 0.99);
+  std::string expected = "SpikyValues:\t99% C.I. 0.089us-2541.825us Avg: 95.033us Max: 10000us\n";
+  hist->PrintConfidenceIntervals(stream, 0.99, data);
   EXPECT_EQ(expected, stream.str());
 }
 
diff --git a/runtime/base/timing_logger.cc b/runtime/base/timing_logger.cc
index dfb0220..e2d2d4c 100644
--- a/runtime/base/timing_logger.cc
+++ b/runtime/base/timing_logger.cc
@@ -79,7 +79,8 @@
   MutexLock mu(Thread::Current(), lock_);
   const std::vector<std::pair<uint64_t, const char*> >& splits = logger.GetSplits();
   typedef std::vector<std::pair<uint64_t, const char*> >::const_iterator It;
-  if (kIsDebugBuild && splits.size() != histograms_.size()) {
+  // The first time this is run, the histograms array will be empty.
+  if (kIsDebugBuild && !histograms_.empty() && splits.size() != histograms_.size()) {
     LOG(ERROR) << "Mismatch in splits.";
     typedef std::vector<Histogram<uint64_t> *>::const_iterator It2;
     It it = splits.begin();
@@ -111,24 +112,24 @@
 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;
-  if (index_ >= histograms_.size()) {
-    Histogram<uint64_t> *tmp_hist = new Histogram<uint64_t>(label);
-    tmp_hist->AddValue(delta_time);
-    histograms_.push_back(tmp_hist);
-  } else {
-    histograms_[index_]->AddValue(delta_time);
-    DCHECK_EQ(label, histograms_[index_]->Name());
+  if (histograms_.size() <= index_) {
+    histograms_.push_back(new Histogram<uint64_t>(label.c_str(), 50));
+    DCHECK_GT(histograms_.size(), index_);
   }
-  index_++;
+  histograms_[index_]->AddValue(delta_time);
+  DCHECK_EQ(label, histograms_[index_]->Name());
+  ++index_;
 }
 
 void CumulativeLogger::DumpHistogram(std::ostream &os) {
   os << "Start Dumping histograms for " << iterations_ << " iterations"
      << " for " << name_ << "\n";
   for (size_t Idx = 0; Idx < histograms_.size(); Idx++) {
-    Histogram<uint64_t> &hist = *(histograms_[Idx]);
-    hist.CreateHistogram();
-    hist.PrintConfidenceIntervals(os, 0.99);
+    Histogram<uint64_t>::CumulativeData cumulative_data;
+    histograms_[Idx]->CreateHistogram(cumulative_data);
+    histograms_[Idx]->PrintConfidenceIntervals(os, 0.99, cumulative_data);
+    // Reset cumulative values to save memory. We don't expect DumpHistogram to be called often, so
+    // it is not performance critical.
   }
   os << "Done Dumping histograms \n";
 }
diff --git a/runtime/gc/space/dlmalloc_space.cc b/runtime/gc/space/dlmalloc_space.cc
index de4917f..a42e880 100644
--- a/runtime/gc/space/dlmalloc_space.cc
+++ b/runtime/gc/space/dlmalloc_space.cc
@@ -131,8 +131,8 @@
   size_t bitmap_index = bitmap_index_++;
 
   static const uintptr_t kGcCardSize = static_cast<uintptr_t>(accounting::CardTable::kCardSize);
-  CHECK_EQ(reinterpret_cast<uintptr_t>(mem_map->Begin()) % kGcCardSize, 0U);
-  CHECK_EQ(reinterpret_cast<uintptr_t>(mem_map->End()) % kGcCardSize, 0U);
+  CHECK(IsAligned<kGcCardSize>(reinterpret_cast<uintptr_t>(mem_map->Begin())));
+  CHECK(IsAligned<kGcCardSize>(reinterpret_cast<uintptr_t>(mem_map->End())));
   live_bitmap_.reset(accounting::SpaceBitmap::Create(
       StringPrintf("allocspace %s live-bitmap %d", name.c_str(), static_cast<int>(bitmap_index)),
       Begin(), Capacity()));
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index 4862c0a..8ff7025 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -56,7 +56,7 @@
 
   std::vector<std::string> arg_vector;
 
-  std::string dex2oat = GetAndroidRoot();
+  std::string dex2oat(GetAndroidRoot());
   dex2oat += (kIsDebugBuild ? "/bin/dex2oatd" : "/bin/dex2oat");
   arg_vector.push_back(dex2oat);