• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 #include "include/CPU.h"
17 #include <sstream>
18 #include <cstdio>
19 #include <unistd.h>
20 #include <cstring>
21 #include <string>
22 #include <iostream>
23 #include <climits>
24 #include "securec.h"
25 #include "include/sp_utils.h"
26 #include "cpu_collector.h"
27 #include "collect_result.h"
28 #include "include/startup_delay.h"
29 #include "include/sp_log.h"
30 #include "include/common.h"
31 #include <dirent.h>
32 
33 using namespace OHOS::HiviewDFX;
34 using namespace OHOS::HiviewDFX::UCollectUtil;
35 using namespace OHOS::HiviewDFX::UCollect;
36 
37 namespace OHOS {
38 namespace SmartPerf {
ItemData()39 std::map<std::string, std::string> CPU::ItemData()
40 {
41     usleep(twenty * thousand);
42     std::map<std::string, std::string> result;
43 
44     GetCpuFreqItemData(result);
45     GetCpuUsageItemData(result);
46     if ((!packageName.empty() || !processId.empty())) {
47         std::map<std::string, std::string> processCpuInfo = CPU::GetSysProcessCpuLoad();
48         if (!processCpuInfo.empty()) {
49             for (const auto& item : processCpuInfo) {
50                 result.insert(item);
51             }
52         }
53     }
54 
55     std::map<std::string, std::string> cpuCoreCurFreqs = GetCpuCoreCurFreqs();
56     for (const auto& item : cpuCoreCurFreqs) {
57         result[item.first] = item.second;
58     }
59 
60     LOGI("CPU:ItemData map size(%u)", result.size());
61     return result;
62 }
63 
GetCpuFreqItemData(std::map<std::string,std::string> & cpuFreqResult)64 void CPU::GetCpuFreqItemData(std::map<std::string, std::string> &cpuFreqResult)
65 {
66     std::vector<CpuFreqs> cpuFreqInfo = GetCpuFreq();
67     for (size_t i = 0; i < cpuFreqInfo.size(); i++) {
68         std::string cpuFreqStr = std::to_string(cpuFreqInfo[i].curFreq);
69         std::string cpuId = std::to_string(cpuFreqInfo[i].cpuId);
70         cpuFreqResult["cpu" + cpuId + "Frequency"] = cpuFreqStr;
71     }
72 }
73 
GetCpuUsageItemData(std::map<std::string,std::string> & cpuUsageResult)74 void CPU::GetCpuUsageItemData(std::map<std::string, std::string> &cpuUsageResult)
75 {
76     std::vector<CpuUsageInfos> workLoads = GetCpuUsage();
77     const size_t oneHundred = 100;
78     if (workLoads.empty()) {
79         return;
80     }
81     for (size_t i = 0; i < workLoads.size(); i++) {
82         std::string cpuIdStr = workLoads[i].cpuId;
83         std::string userUsageStr = std::to_string(workLoads[i].userUsage * oneHundred);
84         std::string niceUsageStr = std::to_string(workLoads[i].niceUsage * oneHundred);
85         std::string systemUsageStr = std::to_string(workLoads[i].systemUsage * oneHundred);
86         std::string idleUsageStr = std::to_string(workLoads[i].idleUsage * oneHundred);
87         std::string ioWaitUsageStr = std::to_string(workLoads[i].ioWaitUsage * oneHundred);
88         std::string irqUsageStr = std::to_string(workLoads[i].irqUsage * oneHundred);
89         std::string softIrqUsageStr = std::to_string(workLoads[i].softIrqUsage * oneHundred);
90         std::string totalUsageStr = std::to_string((workLoads[i].userUsage + workLoads[i].niceUsage +
91             workLoads[i].systemUsage + workLoads[i].ioWaitUsage + workLoads[i].irqUsage + workLoads[i].softIrqUsage) *
92             oneHundred);
93         if (cpuIdStr == cpustr) {
94             cpuIdStr = totalcpu;
95         }
96         cpuUsageResult[cpuIdStr + "userUsage"] = userUsageStr;
97         cpuUsageResult[cpuIdStr + "niceUsage"] = niceUsageStr;
98         cpuUsageResult[cpuIdStr + "systemUsage"] = systemUsageStr;
99         cpuUsageResult[cpuIdStr + "idleUsage"] = idleUsageStr;
100         cpuUsageResult[cpuIdStr + "ioWaitUsage"] = ioWaitUsageStr;
101         cpuUsageResult[cpuIdStr + "irqUsage"] = irqUsageStr;
102         cpuUsageResult[cpuIdStr + "softIrqUsage"] = softIrqUsageStr;
103         cpuUsageResult[cpuIdStr + "Usage"] = totalUsageStr;
104     }
105 }
106 
SetPackageName(const std::string & pName)107 void CPU::SetPackageName(const std::string &pName)
108 {
109     packageName = pName;
110     LOGD("CPU SetPackageName name(%s)", pName.c_str());
111 }
112 
SetProcessId(const std::string & pid)113 void CPU::SetProcessId(const std::string &pid)
114 {
115     LOGD("CPU SetProcessId (%s)", pid.c_str());
116     processId.clear();
117     SPUtils::StrSplit(pid, " ", processId);
118 }
119 
GetCpuFreq()120 std::vector<CpuFreqs> CPU::GetCpuFreq()
121 {
122     OHOS::SmartPerf::CpuFreqs cpuFreqs;
123     std::vector<CpuFreqs> cpuFrequency;
124     std::shared_ptr<CpuCollector> collector = CpuCollector::Create();
125     CollectResult<std::vector<CpuFreq>> result = collector->CollectCpuFrequency();
126     std::vector<CpuFreq> &cpufreq = result.data;
127     for (size_t i = 0; i < cpufreq.size(); i++) {
128         cpuFreqs.cpuId = cpufreq[i].cpuId;
129         cpuFreqs.curFreq = cpufreq[i].curFreq;
130         cpuFrequency.push_back(cpuFreqs);
131     }
132     return cpuFrequency;
133 }
134 
GetCpuUsage()135 std::vector<CpuUsageInfos> CPU::GetCpuUsage()
136 {
137     OHOS::SmartPerf::CpuUsageInfos cpuUsageInfos;
138     std::vector<CpuUsageInfos> workload;
139     std::shared_ptr<CpuCollector> collector = CpuCollector::Create();
140     CollectResult<SysCpuUsage> result = collector->CollectSysCpuUsage(true);
141     SysCpuUsage &sysCpuUsage = result.data;
142     if (sysCpuUsage.cpuInfos.empty()) {
143         return workload;
144     }
145     for (auto &cpuInfo : sysCpuUsage.cpuInfos) {
146         cpuUsageInfos.cpuId = cpuInfo.cpuId;
147         cpuUsageInfos.userUsage = cpuInfo.userUsage;
148         cpuUsageInfos.niceUsage = cpuInfo.niceUsage;
149         cpuUsageInfos.systemUsage = cpuInfo.systemUsage;
150         cpuUsageInfos.idleUsage = cpuInfo.idleUsage;
151         cpuUsageInfos.ioWaitUsage = cpuInfo.ioWaitUsage;
152         cpuUsageInfos.irqUsage = cpuInfo.irqUsage;
153         cpuUsageInfos.softIrqUsage = cpuInfo.softIrqUsage;
154         workload.push_back(cpuUsageInfos);
155     }
156     return workload;
157 }
158 
GetSysProcessCpuLoad() const159 std::map<std::string, std::string> CPU::GetSysProcessCpuLoad() const
160 {
161     std::map<std::string, std::string> processCpuInfo;
162     const size_t oneHundred = 100;
163     if (!processId.empty()) {
164         std::shared_ptr<CpuCollector> collector = CpuCollector::Create();
165         for (size_t i = 0; i < processId.size(); i++) {
166             int32_t procId = SPUtilesTye::StringToSometype<int32_t>(processId[i]);
167             auto collectResult = collector->CollectProcessCpuStatInfo(procId, true);
168             auto data = collectResult.data;
169             if (i == 0) {
170                 processCpuInfo["ProcId"] = std::to_string(data.pid);
171                 processCpuInfo["ProcAppName"] = data.procName;
172                 processCpuInfo["ProcCpuLoad"] = std::to_string(data.cpuLoad * oneHundred);
173                 processCpuInfo["ProcCpuUsage"] = std::to_string(data.cpuUsage * oneHundred);
174                 processCpuInfo["ProcUCpuUsage"] = std::to_string(data.uCpuUsage * oneHundred);
175                 processCpuInfo["ProcSCpuUsage"] = std::to_string(data.sCpuUsage * oneHundred);
176                 GetSysChildProcessCpuLoad(processId.size(), processCpuInfo);
177             } else {
178                 processCpuInfo["ChildProcId"].append(std::to_string(data.pid)).append("|");
179                 processCpuInfo["ChildProcCpuLoad"].append(std::to_string(data.cpuLoad * oneHundred)).append("|");
180                 processCpuInfo["ChildProcCpuUsage"].append(std::to_string(data.cpuUsage * oneHundred)).append("|");
181                 processCpuInfo["ChildProcUCpuUsage"].append(std::to_string(data.uCpuUsage * oneHundred)).append("|");
182                 processCpuInfo["ChildProcSCpuUsage"].append(std::to_string(data.sCpuUsage * oneHundred)).append("|");
183             }
184         }
185     } else {
186         processCpuInfo["ProcId"] = "NA";
187         processCpuInfo["ProcAppName"] = packageName;
188         processCpuInfo["ProcCpuLoad"] = "NA";
189         processCpuInfo["ProcCpuUsage"] = "NA";
190         processCpuInfo["ProcUCpuUsage"] = "NA";
191         processCpuInfo["ProcSCpuUsage"] = "NA";
192         processCpuInfo["ChildProcId"] = "NA";
193         processCpuInfo["ChildProcCpuLoad"] = "NA";
194         processCpuInfo["ChildProcCpuUsage"] = "NA";
195         processCpuInfo["ChildProcUCpuUsage"] = "NA";
196         processCpuInfo["ChildProcSCpuUsage"] = "NA";
197     }
198     GetSysProcessCpuLoadContinue(processCpuInfo);
199     return processCpuInfo;
200 }
201 
GetSysProcessCpuLoadContinue(std::map<std::string,std::string> & processCpuInfo) const202 void CPU::GetSysProcessCpuLoadContinue(std::map<std::string, std::string> &processCpuInfo) const
203 {
204     if (processCpuInfo.find("ProcAppName") != processCpuInfo.end() && processCpuInfo["ProcAppName"].empty()) {
205         processCpuInfo["ProcId"] = "0";
206         processCpuInfo["ProcAppName"] = packageName;
207         processCpuInfo["ProcCpuLoad"] = "0";
208         processCpuInfo["ProcCpuUsage"] = "0";
209         processCpuInfo["ProcUCpuUsage"] = "0";
210         processCpuInfo["ProcSCpuUsage"] = "0";
211         processCpuInfo["ChildProcId"] = "0";
212         processCpuInfo["ChildProcCpuLoad"] = "0";
213         processCpuInfo["ChildProcCpuUsage"] = "0";
214         processCpuInfo["ChildProcUCpuUsage"] = "0";
215         processCpuInfo["ChildProcSCpuUsage"] = "0";
216     }
217 }
218 
GetSysChildProcessCpuLoad(size_t processIdSize,std::map<std::string,std::string> & processCpuInfo) const219 void CPU::GetSysChildProcessCpuLoad(size_t processIdSize, std::map<std::string, std::string> &processCpuInfo) const
220 {
221     if (processIdSize == 1) {
222         processCpuInfo["ChildProcId"] = "NA";
223         processCpuInfo["ChildProcCpuLoad"] = "NA";
224         processCpuInfo["ChildProcCpuUsage"] = "NA";
225         processCpuInfo["ChildProcUCpuUsage"] = "NA";
226         processCpuInfo["ChildProcSCpuUsage"] = "NA";
227     }
228 }
229 
GetCpuCoreCurFreqs()230 std::map<std::string, std::string> CPU::GetCpuCoreCurFreqs()
231 {
232     std::map<std::string, std::string> cpuCoreCurFreqs;
233     std::vector<std::string> policyFiles;
234     std::string basePath = CMD_COMMAND_MAP.at(CmdCommand::CPU_FREQ);
235     DIR *dir = opendir(basePath.c_str());
236     if (dir == nullptr) {
237         LOGE("CPU::CPU_FREQ dir open failed.");
238         return cpuCoreCurFreqs;
239     }
240     bool isCpuCoreCurFreqs = true;
241     while (isCpuCoreCurFreqs) {
242         struct dirent *ptr = readdir(dir);
243         if (ptr == nullptr) {
244             break;
245         }
246         if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0)) {
247             continue;
248         }
249         std::string clusterName = std::string(ptr->d_name);
250         policyFiles.push_back(SPUtils::IncludePathDelimiter(basePath) + clusterName);
251     }
252     closedir(dir);
253     for (size_t i = 0; i < policyFiles.size(); i++) {
254         std::string curFreq;
255         SPUtils::LoadFile(policyFiles[i] + "/cpuinfo_cur_freq", curFreq);
256         std::string nameBase = "cpu" + std::to_string(i) + "_";
257         cpuCoreCurFreqs[nameBase + "curFrequency"] = curFreq;
258     }
259     return cpuCoreCurFreqs;
260 }
261 }
262 }
263