• 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 <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