1 /** 2 * Copyright (c) 2024 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef LIBPANDABASE_MEM_WEIGHTED_ADAPTIVE_TLAB_AVERAGE_H 17 #define LIBPANDABASE_MEM_WEIGHTED_ADAPTIVE_TLAB_AVERAGE_H 18 19 #include <algorithm> 20 #include "libpandabase/macros.h" 21 #include "runtime/include/mem/panda_containers.h" 22 23 namespace ark { 24 class WeightedAdaptiveTlabAverage { 25 public: WeightedAdaptiveTlabAverage(float initTlabSize,float upperSumBorder,float maxGrowRatio,float weight,float desiredFillFraction)26 explicit WeightedAdaptiveTlabAverage(float initTlabSize, float upperSumBorder, float maxGrowRatio, float weight, 27 float desiredFillFraction) 28 : maxGrowRatio_(maxGrowRatio), 29 lowerSumBorder_(initTlabSize), 30 upperSumBorder_(upperSumBorder), 31 lastCountedSum_(initTlabSize), 32 weight_(weight), 33 desiredFillFraction_(desiredFillFraction) 34 { 35 ASSERT(maxGrowRatio_ > 1.0); 36 } 37 StoreNewSample(size_t occupiedSize,size_t maxSize)38 void StoreNewSample(size_t occupiedSize, size_t maxSize) 39 { 40 // Supposed that this method is called only in case of slow path 41 ASSERT(occupiedSize <= maxSize); 42 samples_.emplace_back(std::make_pair(occupiedSize, maxSize)); 43 } 44 45 /** 46 * @brief Estimates new TLAB size using saved TLABs' information 47 * 48 * If vector with samples is not empty, we start estimating TLABs' average fill fraction 49 * If average fill fraction is less than desiredFillFraction_, then we increase TLABs' size 50 * Else, we reduce TLABs' size 51 */ ComputeNewSumAndResetSamples()52 void ComputeNewSumAndResetSamples() 53 { 54 float newCountedSum = lastCountedSum_; 55 if (!samples_.empty()) { 56 float averageFillFraction = -1.0; 57 // Average fill fraction estimation 58 for (auto &sample : samples_) { 59 if (sample.second != 0) { 60 averageFillFraction = averageFillFraction < 0 61 ? static_cast<float>(sample.first) / sample.second 62 : static_cast<float>(sample.first) / sample.second * weight_ + 63 averageFillFraction * (1.0F - weight_); 64 } 65 } 66 if (averageFillFraction < 0) { 67 // it means that zero tlab is the only sample that we currently have 68 // in this case we don't have enough information to calculate new TLAB size 69 samples_.clear(); 70 return; 71 } 72 if (averageFillFraction < desiredFillFraction_) { 73 // Should increase TLABs' size 74 newCountedSum = std::clamp(lastCountedSum_ * (desiredFillFraction_ / averageFillFraction), 75 lastCountedSum_ / maxGrowRatio_, lastCountedSum_ * maxGrowRatio_); 76 } else { 77 // In this case we have few TLABs with good average fill fraction 78 // It means that we should consider reducing TLABs' size 79 newCountedSum = lastCountedSum_ * REDUCTION_RATE; 80 } 81 } 82 // Mind lower and upper borders 83 lastCountedSum_ = 84 std::clamp(newCountedSum * weight_ + lastCountedSum_ * (1.0F - weight_), lowerSumBorder_, upperSumBorder_); 85 samples_.clear(); 86 } 87 GetLastCountedSum()88 float GetLastCountedSum() const 89 { 90 return lastCountedSum_; 91 } 92 GetLastCountedSumInSizeT()93 size_t GetLastCountedSumInSizeT() const 94 { 95 ASSERT(lowerSumBorder_ <= lastCountedSum_); 96 ASSERT(lastCountedSum_ <= upperSumBorder_); 97 return static_cast<size_t>(lastCountedSum_); 98 } 99 100 private: 101 static constexpr float REDUCTION_RATE = 0.75; // Value used for size reduction 102 float maxGrowRatio_; // Max change ratio when new average is estimated 103 // (means that (newAverage / average) < maxGrowRatio_) 104 float lowerSumBorder_; // Min value that sum may take 105 float upperSumBorder_; // Max value that sum may take 106 float lastCountedSum_; // Last estimated sum 107 float weight_; // From 0 to 1 108 // Used for better average estimation 109 // Recently observed samples should have greater weight 110 float desiredFillFraction_; // From 0 to 1 111 // If (occupiedSize / maxSize) < desiredFillFraction_ then 112 // lastCountedSum_ should grow 113 PandaVector<std::pair<size_t, size_t>> samples_; // Saved samples. Used for estimation of a new sum 114 }; 115 116 } // namespace ark 117 #endif // LIBPANDABASE_MEM_WEIGHTED_ADAPTIVE_TLAB_AVERAGE_H 118