• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "histogram.h"
18 
19 #include <sstream>
20 #include <cmath>
21 
22 #define LOG_TAG "TuningFork"
23 #include "Log.h"
24 
25 #include "clearcutserializer.h"
26 
27 namespace tuningfork {
28 
Histogram(float start_ms,float end_ms,int num_buckets_between)29 Histogram::Histogram(float start_ms, float end_ms, int num_buckets_between)
30     : start_ms_(start_ms), end_ms_(end_ms),
31       bucket_dt_ms_((end_ms_ - start_ms_) / num_buckets_between),
32       num_buckets_(num_buckets_between + 2),
33       buckets_(num_buckets_), auto_range_(start_ms_ == 0 && end_ms_ == 0), count_(0) {
34     std::fill(buckets_.begin(), buckets_.end(), 0);
35     if (auto_range_)
36         samples_.reserve(num_buckets_);
37     else if (bucket_dt_ms_ <= 0)
38         ALOGE("Histogram end needs to be larger than histogram begin");
39 }
40 
Histogram(const Settings::Histogram & hs)41 Histogram::Histogram(const Settings::Histogram &hs)
42     : Histogram(hs.bucket_min, hs.bucket_max, hs.n_buckets) {
43 }
44 
Add(Sample dt_ms)45 void Histogram::Add(Sample dt_ms) {
46     if (auto_range_) {
47         samples_.push_back(dt_ms);
48         if (samples_.size() == samples_.capacity()) {
49             CalcBucketsFromSamples();
50         }
51     } else {
52         int i = (dt_ms - start_ms_) / bucket_dt_ms_;
53         if (i < 0)
54             buckets_[0]++;
55         else if (i + 1 >= num_buckets_)
56             buckets_[num_buckets_ - 1]++;
57         else
58             buckets_[i + 1]++;
59         ++count_;
60     }
61 }
62 
CalcBucketsFromSamples()63 void Histogram::CalcBucketsFromSamples() {
64     Sample min_dt = std::numeric_limits<Sample>::max();
65     Sample max_dt = std::numeric_limits<Sample>::min();
66     Sample sum = 0;
67     Sample sum2 = 0;
68     for (Sample d: samples_) {
69         if (d < min_dt) min_dt = d;
70         if (d > max_dt) max_dt = d;
71         sum += d;
72         sum2 += d * d;
73     }
74     size_t n = samples_.size();
75     Sample mean = sum / n;
76     Sample var = sum2 / n - mean * mean;
77     if (var < 0) var = 0; // Can be negative due to rounding errors
78     Sample stddev = sqrt(var);
79     start_ms_ = std::max(mean - kAutoSizeNumStdDev * stddev, 0.0);
80     end_ms_ = mean + kAutoSizeNumStdDev * stddev;
81     bucket_dt_ms_ = (end_ms_ - start_ms_) / (num_buckets_ - 2);
82     if (bucket_dt_ms_ < kAutoSizeMinBucketSizeMs) {
83         bucket_dt_ms_ = kAutoSizeMinBucketSizeMs;
84         Sample w = bucket_dt_ms_ * (num_buckets_ - 2);
85         start_ms_ = mean - w / 2;
86         end_ms_ = mean + w / 2;
87     }
88     auto_range_ = false;
89     for (Sample d: samples_) {
90         Add(d);
91     }
92 }
93 
ToJSON() const94 std::string Histogram::ToJSON() const {
95     std::stringstream str;
96     str.precision(2);
97     str << std::fixed;
98     if (auto_range_) {
99         str << "{\"pmax\":[],\"cnts\":[]}";
100     } else {
101         str << "{\"pmax\":[";
102         Sample x = start_ms_;
103         for (int i = 0; i < num_buckets_ - 1; ++i) {
104             str << x << ",";
105             x += bucket_dt_ms_;
106         }
107         str << "99999],\"cnts\":[";
108         for (int i = 0; i < num_buckets_ - 1; ++i) {
109             str << buckets_[i] << ",";
110         }
111         if (num_buckets_ > 0)
112             str << buckets_.back();
113         str << "]}";
114     }
115     return str.str();
116 }
117 
Clear(bool autorange)118 void Histogram::Clear(bool autorange) {
119     std::fill(buckets_.begin(), buckets_.end(), 0);
120     samples_.clear();
121     auto_range_ = autorange;
122     count_ = 0;
123 }
124 
125 } // namespace tuningfork
126