1 /* 2 * Copyright (c) 2023-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 #include "cpu_calculator.h" 16 17 #include <cinttypes> 18 19 #include "file_util.h" 20 #include "hiview_logger.h" 21 #include "string_util.h" 22 23 namespace OHOS { 24 namespace HiviewDFX { 25 namespace UCollectUtil { 26 DEFINE_LOG_TAG("UCollectUtil-CpuCalculator"); 27 namespace { CalcSysCpuTotalTime(const CpuTimeInfo & cpuTimeInfo)28 uint32_t CalcSysCpuTotalTime(const CpuTimeInfo& cpuTimeInfo) 29 { 30 return cpuTimeInfo.userTime + cpuTimeInfo.niceTime + cpuTimeInfo.systemTime + cpuTimeInfo.idleTime 31 + cpuTimeInfo.ioWaitTime + cpuTimeInfo.irqTime + cpuTimeInfo.softIrqTime; 32 } 33 CalcSysCpuUsage(uint32_t deltaTime,uint32_t currTime,uint32_t lastTime)34 double CalcSysCpuUsage(uint32_t deltaTime, uint32_t currTime, uint32_t lastTime) 35 { 36 return currTime <= lastTime ? 0 : (((currTime - lastTime) * 1.0) / deltaTime); 37 } 38 } 39 CpuCalculator()40 CpuCalculator::CpuCalculator() 41 { 42 InitNumOfCpuCores(); 43 InitCpuDmipses(); 44 InitMaxCpuLoadUnit(); 45 } 46 InitNumOfCpuCores()47 void CpuCalculator::InitNumOfCpuCores() 48 { 49 numOfCpuCores_ = CpuUtil::GetNumOfCpuCores(); 50 } 51 InitCpuDmipses()52 void CpuCalculator::InitCpuDmipses() 53 { 54 for (uint32_t i = 0; i < numOfCpuCores_; i++) { 55 std::string cpuCapacityFilePath = SYS_CPU_DIR_PREFIX + std::to_string(i) + "/cpu_capacity"; 56 std::string cpuCapacityFileContent = FileUtil::GetFirstLine(cpuCapacityFilePath); 57 if (cpuCapacityFileContent.empty()) { 58 HIVIEW_LOGE("failed to get cpu capacity content from file=%{public}s", cpuCapacityFileContent.c_str()); 59 return; 60 } 61 uint32_t dmipse = StringUtil::StringToUl(cpuCapacityFileContent); 62 cpuDmipses_.emplace_back(dmipse); 63 HIVIEW_LOGD("get cpu=%{public}u capacity value=%{public}u", i, dmipse); 64 } 65 } 66 InitMaxCpuLoadUnit()67 void CpuCalculator::InitMaxCpuLoadUnit() 68 { 69 maxCpuLoadUnit_ = IsSMTEnabled() ? GetMaxStCpuLoadWithSMT() : GetMaxStCpuLoad(); 70 HIVIEW_LOGD("init max cpu load unit=%{public}" PRIu64, maxCpuLoadUnit_); 71 } 72 IsSMTEnabled()73 bool CpuCalculator::IsSMTEnabled() 74 { 75 constexpr uint32_t numOfCpuCoresWithSMT = 12; 76 return numOfCpuCores_ == numOfCpuCoresWithSMT; 77 } 78 GetMaxStCpuLoad()79 uint64_t CpuCalculator::GetMaxStCpuLoad() 80 { 81 uint64_t maxStCpuLoadSum = 0; 82 for (uint32_t cpuCoreIndex = 0; cpuCoreIndex < numOfCpuCores_; cpuCoreIndex++) { 83 if (cpuCoreIndex >= cpuDmipses_.size()) { 84 HIVIEW_LOGW("failed to get max st load from cpu=%{public}u", cpuCoreIndex); 85 continue; 86 } 87 maxStCpuLoadSum += cpuDmipses_[cpuCoreIndex]; 88 } 89 return maxStCpuLoadSum; 90 } 91 GetMaxStCpuLoadWithSMT()92 uint64_t CpuCalculator::GetMaxStCpuLoadWithSMT() 93 { 94 uint64_t maxStCpuLoadSum = 0; 95 for (uint32_t cpuCoreIndex = 0; cpuCoreIndex < numOfCpuCores_; cpuCoreIndex++) { 96 if (cpuCoreIndex >= cpuDmipses_.size()) { 97 HIVIEW_LOGW("failed to get max st load with smt from cpu=%{public}u", cpuCoreIndex); 98 continue; 99 } 100 uint32_t tmpDmipse = cpuDmipses_[cpuCoreIndex]; 101 constexpr uint32_t maxIndexOfSmallCore = 3; // small cores do not support smt 102 if (cpuCoreIndex > maxIndexOfSmallCore) { 103 constexpr uint32_t capDiscount = 65; 104 tmpDmipse = tmpDmipse * capDiscount / 100; // 100: % 105 } 106 maxStCpuLoadSum += tmpDmipse; 107 } 108 return maxStCpuLoadSum; 109 } 110 CalculateCpuLoad(uint64_t currCpuLoad,uint64_t lastCpuLoad,uint64_t statPeriod)111 double CpuCalculator::CalculateCpuLoad(uint64_t currCpuLoad, uint64_t lastCpuLoad, uint64_t statPeriod) 112 { 113 if (lastCpuLoad > currCpuLoad || statPeriod == 0) { 114 HIVIEW_LOGW("invalid params, currCpuLoad=%{public}" PRIu64 ", lastCpuLoad=%{public}" PRIu64 115 ", statPeriod=%{public}" PRIu64, currCpuLoad, lastCpuLoad, statPeriod); 116 return 0; 117 } 118 if (maxCpuLoadUnit_ == 0) { 119 HIVIEW_LOGW("invalid num of max cpu load unit"); 120 return 0; 121 } 122 uint64_t maxCpuLoadOfSystemInStatPeriod = statPeriod * maxCpuLoadUnit_; 123 uint64_t cpuLoadInStatPeriod = currCpuLoad - lastCpuLoad; 124 return ((cpuLoadInStatPeriod * 1.0) / maxCpuLoadOfSystemInStatPeriod); 125 } 126 CalculateCpuUsage(uint64_t currCpuUsage,uint64_t lastCpuUsage,uint64_t statPeriod)127 double CpuCalculator::CalculateCpuUsage(uint64_t currCpuUsage, uint64_t lastCpuUsage, uint64_t statPeriod) 128 { 129 if (lastCpuUsage > currCpuUsage || statPeriod == 0) { 130 HIVIEW_LOGW("invalid params, currCpuUsage=%{public}" PRIu64 ", lastCpuUsage=%{public}" PRIu64 131 ", statPeriod=%{public}" PRIu64, currCpuUsage, lastCpuUsage, statPeriod); 132 return 0; 133 } 134 if (numOfCpuCores_ == 0) { 135 HIVIEW_LOGW("invalid num of cpu cores"); 136 return 0; 137 } 138 uint64_t cpuUsageInStatPeriod = currCpuUsage - lastCpuUsage; 139 uint64_t totalCpuUsageOfSystemInStatPeriod = statPeriod * numOfCpuCores_; 140 return ((cpuUsageInStatPeriod * 1.0) / totalCpuUsageOfSystemInStatPeriod); 141 } 142 CalculateSysCpuUsageInfo(const CpuTimeInfo & currCpuTimeInfo,const CpuTimeInfo & lastCpuTimeInfo)143 CpuUsageInfo CpuCalculator::CalculateSysCpuUsageInfo(const CpuTimeInfo& currCpuTimeInfo, 144 const CpuTimeInfo& lastCpuTimeInfo) 145 { 146 CpuUsageInfo calcInfo; 147 calcInfo.cpuId = currCpuTimeInfo.cpuId; 148 uint32_t currTotalTime = CalcSysCpuTotalTime(currCpuTimeInfo); 149 uint32_t lastTotalTime = CalcSysCpuTotalTime(lastCpuTimeInfo); 150 if (currTotalTime <= lastTotalTime) { 151 return calcInfo; 152 } 153 154 uint32_t deltaTime = currTotalTime - lastTotalTime; 155 calcInfo.userUsage = CalcSysCpuUsage(deltaTime, currCpuTimeInfo.userTime, lastCpuTimeInfo.userTime); 156 calcInfo.niceUsage = CalcSysCpuUsage(deltaTime, currCpuTimeInfo.niceTime, lastCpuTimeInfo.niceTime); 157 calcInfo.systemUsage = CalcSysCpuUsage(deltaTime, currCpuTimeInfo.systemTime, lastCpuTimeInfo.systemTime); 158 calcInfo.idleUsage = CalcSysCpuUsage(deltaTime, currCpuTimeInfo.idleTime, lastCpuTimeInfo.idleTime); 159 calcInfo.ioWaitUsage = CalcSysCpuUsage(deltaTime, currCpuTimeInfo.ioWaitTime, lastCpuTimeInfo.ioWaitTime); 160 calcInfo.irqUsage = CalcSysCpuUsage(deltaTime, currCpuTimeInfo.irqTime, lastCpuTimeInfo.irqTime); 161 calcInfo.softIrqUsage = CalcSysCpuUsage(deltaTime, currCpuTimeInfo.softIrqTime, lastCpuTimeInfo.softIrqTime); 162 return calcInfo; 163 } 164 GetCpuDmipses()165 std::vector<uint32_t> CpuCalculator::GetCpuDmipses() 166 { 167 return cpuDmipses_; 168 } 169 } // UCollectUtil 170 } // HiViewDFX 171 } // OHOS 172