1 /*
2  * Copyright (C) 2021 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 #ifndef CHRE_UTIL_SYSTEM_STATS_CONTAINER_H_
18 #define CHRE_UTIL_SYSTEM_STATS_CONTAINER_H_
19 
20 #include <cinttypes>
21 #include <type_traits>
22 
23 #include "chre/util/macros.h"
24 
25 namespace chre {
26 
27 /**
28  * A Stats tool used to collect and compute metrics of interests
29  */
30 
31 template <typename T>
32 class StatsContainer {
33   static_assert(std::is_arithmetic<T>::value,
34                 "Type must support arithmetic operations");
35 
36  public:
37   /**
38    * @brief Construct a new Stats Container object
39    *
40    * @param averageWindow_ how many data stored before prioritizing new data,
41    * it should not be bigger than the default value to prevent rounding to 0
42    */
43   StatsContainer(uint32_t averageWindow_ = 512)
mAverageWindow(averageWindow_)44       : mAverageWindow(averageWindow_) {}
45 
46   /**
47    * Add a new value to the metric collection and update mean/max value
48    * Mean calculated in rolling bases to prevent overflow by accumulating too
49    * much data.
50    *
51    * Before mCount reaches mAverageWindow, it calculates the normal average
52    * After mCount reaches mAverageWindow, weighted average is used to prioritize
53    * recent data where the new value always contributes 1/mAverageWindow amount
54    * to the average
55    * @param value a T instance
56    */
addValue(T value)57   void addValue(T value) {
58     if (mCount < mAverageWindow) {
59       ++mCount;
60     }
61     mMean = (mCount - 1) * (mMean / mCount) + value / mCount;
62     mMax = MAX(value, mMax);
63   }
64 
65   /**
66    * @return the average value calculated by the description of the
67    * addValue method
68    */
getMean()69   T getMean() const {
70     return mMean;
71   }
72 
73   /**
74    * @return the max value
75    */
getMax()76   T getMax() const {
77     return mMax;
78   }
79 
80   /**
81    * @return the average window
82    */
getAverageWindow()83   uint32_t getAverageWindow() const {
84     return mAverageWindow;
85   }
86 
87  private:
88   //! Mean of the collections of this stats
89   T mMean = 0;
90   //! Number of collections of this stats
91   uint32_t mCount = 0;
92   //! The Window that the container will not do weighted average
93   uint32_t mAverageWindow;
94   //! Max of stats
95   T mMax = 0;
96 };
97 
98 }  // namespace chre
99 
100 #endif  // CHRE_UTIL_SYSTEM_STATS_CONTAINER_H_
101