1 // 2 // 3 // Copyright 2015 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPC_SRC_CORE_LIB_GPRPP_TIME_AVERAGED_STATS_H 20 #define GRPC_SRC_CORE_LIB_GPRPP_TIME_AVERAGED_STATS_H 21 22 namespace grpc_core { 23 24 // This tracks a time-decaying weighted average. It works by collecting 25 // batches of samples and then mixing their average into a time-decaying 26 // weighted mean. It is designed for batch operations where we do many adds 27 // before updating the average. 28 29 class TimeAveragedStats { 30 public: 31 TimeAveragedStats(double init_avg, double regress_weight, 32 double persistence_factor); 33 34 // Add a sample to the current batch. 35 void AddSample(double value); 36 // Complete a batch and compute the new estimate of the average sample 37 // value. 38 double UpdateAverage(); 39 aggregate_weighted_avg()40 double aggregate_weighted_avg() const { return aggregate_weighted_avg_; } aggregate_total_weight()41 double aggregate_total_weight() const { return aggregate_total_weight_; } 42 43 private: 44 // The initial average value. This is the reported average until the first 45 // grpc_time_averaged_stats_update_average call. If a positive regress_weight 46 // is used, we also regress towards this value on each update. 47 const double init_avg_; 48 // The sample weight of "init_avg" that is mixed in with each call to 49 // grpc_time_averaged_stats_update_average. If the calls to 50 // grpc_time_averaged_stats_add_sample stop, this will cause the average to 51 // regress back to the mean. This should be non-negative. Set it to 0 to 52 // disable the bias. A value of 1 has the effect of adding in 1 bonus sample 53 // with value init_avg to each sample period. 54 const double regress_weight_; 55 // This determines the rate of decay of the time-averaging from one period 56 // to the next by scaling the aggregate_total_weight of samples from prior 57 // periods when combining with the latest period. It should be in the range 58 // [0,1]. A higher value adapts more slowly. With a value of 0.5, if the 59 // batches each have k samples, the samples_in_avg_ will grow to 2 k, so the 60 // weighting of the time average will eventually be 1/3 new batch and 2/3 61 // old average. 62 const double persistence_factor_; 63 64 // The total value of samples since the last UpdateAverage(). 65 double batch_total_value_ = 0; 66 // The number of samples since the last UpdateAverage(). 67 double batch_num_samples_ = 0; 68 // The time-decayed sum of batch_num_samples_ over previous batches. This is 69 // the "weight" of the old aggregate_weighted_avg_ when updating the 70 // average. 71 double aggregate_total_weight_ = 0; 72 // A time-decayed average of the (batch_total_value_ / batch_num_samples_), 73 // computed by decaying the samples_in_avg_ weight in the weighted average. 74 double aggregate_weighted_avg_ = init_avg_; 75 }; 76 77 } // namespace grpc_core 78 79 #endif // GRPC_SRC_CORE_LIB_GPRPP_TIME_AVERAGED_STATS_H 80