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