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 <sstream>
17 #include <cstdio>
18 #include <cstring>
19 #include <climits>
20 #include "securec.h"
21 #include "include/sp_utils.h"
22 #include "include/CPU.h"
23 namespace OHOS {
24 namespace SmartPerf {
ItemData()25 std::map<std::string, std::string> CPU::ItemData()
26 {
27 std::map<std::string, std::string> result;
28 if (mCpuNum < 0) {
29 GetCpuNum();
30 }
31 std::vector<float> workloads = GetCpuLoad();
32 std::string cpuLoadsStr;
33 std::string cpuFreqStr;
34 for (size_t i = 0; i < workloads.size(); i++) {
35 cpuLoadsStr = std::to_string(workloads[i]);
36 cpuFreqStr = std::to_string(GetCpuFreq(i));
37 result["cpu" + std::to_string(i) + "Load"] = cpuLoadsStr;
38 result["cpu" + std::to_string(i) + "Frequency"] = cpuFreqStr;
39 }
40 return result;
41 }
GetCpuNum()42 int CPU::GetCpuNum()
43 {
44 int cpuNum = 0;
45 while (true) {
46 std::stringstream cpuNodeStr;
47 cpuNodeStr << cpuBasePath.c_str() << "/cpu" << cpuNum;
48 if (!SPUtils::FileAccess(cpuNodeStr.str())) {
49 break;
50 }
51 ++cpuNum;
52 }
53 return mCpuNum = cpuNum;
54 }
GetCpuFreq(int cpuId) const55 int CPU::GetCpuFreq(int cpuId) const
56 {
57 std::string curFreq = "-1";
58 SPUtils::LoadFile(CpuScalingCurFreq(cpuId), curFreq);
59 return atoi(curFreq.c_str());
60 }
GetCpuLoad()61 std::vector<float> CPU::GetCpuLoad()
62 {
63 if (mCpuNum <= 0) {
64 std::vector<float> workload;
65 return workload;
66 }
67 std::vector<float> workload;
68
69 static char preBuffer[10][256] = {"\0", "\0", "\0", "\0", "\0", "\0", "\0", "\0", "\0", "\0"};
70 if (!SPUtils::FileAccess(procStat)) {
71 return workload;
72 }
73 char realPath[PATH_MAX] = {0x00};
74 if (realpath(procStat.c_str(), realPath) == nullptr) {
75 std::cout << "" << std::endl;
76 }
77 FILE *fp = fopen(realPath, "r");
78 if (fp == nullptr) {
79 for (int i = 0; i <= mCpuNum; ++i) {
80 workload.push_back(-1.0f);
81 }
82 return workload;
83 }
84 char buffer[1024];
85 buffer[0] = '\0';
86 int line = 0;
87 while (fgets(buffer, sizeof(buffer), fp) != nullptr) {
88 const int zeroPos = 0;
89 const int firstPos = 1;
90 const int secondPos = 2;
91 const int length = 3;
92 if (strlen(buffer) >= length && buffer[zeroPos] == 'c' && buffer[firstPos] == 'p' && buffer[secondPos] == 'u' &&
93 line != 0) {
94 float b = CacWorkload(buffer, preBuffer[line]);
95 workload.push_back(b);
96 if (snprintf_s(preBuffer[line], sizeof(preBuffer[line]), sizeof(preBuffer[line]), "%s", buffer) < 0) {
97 std::cout << "snprintf_s turn fail" << std::endl;
98 }
99 }
100 ++line;
101
102 if (line >= mCpuNum + 1) {
103 break;
104 }
105 }
106 if (fclose(fp) == EOF) {
107 return workload;
108 }
109
110 return workload;
111 }
112
CacWorkload(const char * buffer,const char * preBuffer) const113 float CPU::CacWorkload(const char *buffer, const char *preBuffer) const
114 {
115 const size_t defaultIndex = 4;
116 const size_t defaultShift = 10;
117 const char defaultStart = '0';
118 const char defaultEnd = '9';
119
120 size_t preLen = strlen(preBuffer);
121 size_t len = strlen(buffer);
122 if (preLen == 0 || len == 0) {
123 return -1.0f;
124 }
125 size_t time[10] = {0};
126 size_t preTime[10] = {0};
127 size_t cnt = 0;
128
129 for (size_t i = defaultIndex; i < len; ++i) {
130 size_t tmp = 0;
131 if (buffer[i] < defaultStart || buffer[i] > defaultEnd) {
132 continue;
133 }
134 while (buffer[i] >= defaultStart && buffer[i] <= defaultEnd) {
135 tmp = tmp * defaultShift + (buffer[i] - defaultStart);
136 i++;
137 }
138 time[cnt++] = tmp;
139 }
140
141 size_t preCnt = 0;
142 for (size_t i = defaultIndex; i < preLen; ++i) {
143 size_t tmp = 0;
144 if (preBuffer[i] < defaultStart || preBuffer[i] > defaultEnd) {
145 continue;
146 }
147 while (preBuffer[i] >= defaultStart && preBuffer[i] <= defaultEnd) {
148 tmp = tmp * defaultShift + (preBuffer[i] - defaultStart);
149 i++;
150 }
151 preTime[preCnt++] = tmp;
152 }
153
154 size_t user = time[0] + time[1] - preTime[0] - preTime[1];
155 size_t sys = time[2] - preTime[2];
156 size_t idle = time[3] - preTime[3];
157 size_t iowait = time[4] - preTime[4];
158 size_t irq = time[5] + time[6] - preTime[5] - preTime[6];
159 size_t total = user + sys + idle + iowait + irq;
160
161 double perUser = std::atof(std::to_string(user * 100.0 / total).c_str());
162 double perSys = std::atof(std::to_string(sys * 100.0 / total).c_str());
163 double periowait = std::atof(std::to_string(iowait * 100.0 / total).c_str());
164 double perirq = std::atof(std::to_string(irq * 100.0 / total).c_str());
165
166 double workload = perUser + perSys + periowait + perirq;
167
168 return static_cast<float>(workload);
169 }
170 }
171 }
172