• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) Huawei Technologies Co., Ltd. 2023. All rights reserved.
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 <cstdio>
16 #include <algorithm>
17 #include <iostream>
18 #include <sstream>
19 #include <queue>
20 #include <vector>
21 #include <map>
22 #include <string>
23 #include <ctime>
24 #include <thread>
25 #include <unistd.h>
26 #include <sys/time.h>
27 #include "include/profiler_fps.h"
28 #include "include/sp_log.h"
29 #include "include/sp_utils.h"
30 #include "include/ByTrace.h"
31 
32 
33 namespace OHOS {
34 namespace SmartPerf {
ItemData()35 std::map<std::string, std::string> ProfilerFPS::ItemData()
36 {
37     std::map<std::string, std::string> result;
38     FpsInfoProfiler finalResult = GetFpsInfo();
39     lastFpsInfoResult = finalResult;
40     result["fps"] = std::to_string(finalResult.fps);
41     LOGI("ProfilerFPS.result.fps====: %s", std::to_string(finalResult.fps).c_str());
42     LOGI("ProfilerFPS.result.curTime====: %s", std::to_string(finalResult.curTime).c_str());
43     std::string jitterStr = "";
44     std::string split = "";
45     for (size_t i = 0; i < finalResult.jitters.size(); i++) {
46         if (i > 0) {
47             split = ";;";
48         }
49         jitterStr += split + std::to_string(finalResult.jitters[i]);
50     }
51     result["fpsJitters"] = jitterStr;
52     LOGI("ProfilerFPS.result.jitters====: %s", jitterStr.c_str());
53     if (isCatchTrace > 0) {
54         ByTrace::GetInstance().CheckFpsJitters(finalResult.jitters, finalResult.fps);
55     }
56     return result;
57 }
58 
SetTraceCatch()59 void ProfilerFPS::SetTraceCatch()
60 {
61     isCatchTrace = 1;
62 }
63 
SetPackageName(std::string pName)64 void ProfilerFPS::SetPackageName(std::string pName)
65 {
66     pkgName = std::move(pName);
67 }
68 
GetResultFPS(int sectionsNum)69 void ProfilerFPS::GetResultFPS(int sectionsNum)
70 {
71     struct timeval start;
72     struct timeval end;
73     gettimeofday(&start, nullptr);
74     FpsInfoProfiler fpsInfoResult;
75     unsigned long runTime;
76     fpsInfoResult = GetFpsInfo();
77     if (fpsInfoResult.fps == 0) {
78         if (lastCurrTime == 0) {
79             long long currTime = (fpsInfoResult.currTimeDump / msClear) * msClear + fpsInfoResult.currTimeDiff;
80             lastCurrTime = currTime / oneSec;
81             printf("fps:%d|%lld\n", fpsInfoResult.fps, currTime / oneSec);
82         } else {
83             printf("fps:%d|%lld\n", fpsInfoResult.fps, lastCurrTime + oneThousand);
84             lastCurrTime = lastCurrTime + oneThousand;
85         }
86     } else {
87         long long currTime = (fpsInfoResult.currTimeStamps[0] / msClear) * msClear + fpsInfoResult.currTimeDiff;
88         lastCurrTime = currTime / oneSec;
89         printf("fps:%d|%lld\n", fpsInfoResult.fps, lastCurrTime);
90     }
91     lastFpsInfoResult = fpsInfoResult;
92     if (sectionsNum == ten && fpsInfoResult.fps != 0) {
93         GetSectionsFps(fpsInfoResult);
94     }
95     time_t now = time(nullptr);
96     if (now == -1) {
97         LOGI("Failed to get current time.");
98         return;
99     }
100     char *dt = ctime(&now);
101     LOGI("printf time is: %s", dt);
102     fflush(stdout);
103     gettimeofday(&end, nullptr);
104     runTime = end.tv_sec * 1e6 - start.tv_sec * 1e6 + end.tv_usec - start.tv_usec;
105     LOGI("printf time is---runTime: %s", std::to_string(runTime).c_str());
106     if (runTime < sleepTime) {
107         usleep(sleepTime - runTime);
108     }
109     GetCurrentTime(ten);
110 }
111 
GetCurrentTime(int sleepNum)112 void ProfilerFPS::GetCurrentTime(int sleepNum)
113 {
114     for (int i = 0; i < sleepNum; i++) {
115         struct timespec time1 = { 0 };
116         clock_gettime(CLOCK_MONOTONIC, &time1);
117         int curTimeNow = static_cast<int>(time1.tv_sec - 1);
118         if (curTimeNow == lastFpsInfoResult.curTime) {
119             usleep(sleepNowTime);
120         } else {
121             break;
122         }
123     }
124 }
125 
GetTimeDiff()126 void ProfilerFPS::GetTimeDiff()
127 {
128     long long clockRealTime = 0;
129     long long clockMonotonicRaw = 0;
130     int two = 2;
131     std::string strRealTime;
132     std::string cmd = "timestamps";
133     FILE *fd = popen(cmd.c_str(), "r");
134     if (fd == nullptr) {
135         return;
136     }
137     char buf[1024] = {'\0'};
138     while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
139         std::string line = buf;
140         std::vector<std::string> params;
141         SPUtils::StrSplit(line, " ", params);
142         if (params[0].find("CLOCK_REALTIME") != std::string::npos && clockRealTime == 0) {
143             strRealTime = params[two];
144             strRealTime.erase(strRealTime.find('.'), 1);
145             clockRealTime = std::stoll(strRealTime);
146             currRealTime = clockRealTime;
147         } else if (params[0].find("CLOCK_MONOTONIC_RAW") != std::string::npos && clockMonotonicRaw == 0) {
148             strRealTime = params[two];
149             strRealTime.erase(strRealTime.find('.'), 1);
150             clockMonotonicRaw = std::stoll(strRealTime);
151         }
152     }
153     pclose(fd);
154     fpsInfo.currTimeDiff = clockRealTime - clockMonotonicRaw;
155 }
156 
GetSectionsPrint(int printCount,long long msStartTime) const157 void ProfilerFPS::GetSectionsPrint(int printCount, long long msStartTime) const
158 {
159     if (printCount < ten) {
160         for (int i = 0; i < ten - printCount; i++) {
161             long long msJiange = 100;
162             msStartTime += msJiange;
163             printf("sectionsFps:%d|%lld\n", 0, msStartTime);
164         }
165     }
166 }
167 
GetSectionsFps(FpsInfoProfiler & fpsInfoResult) const168 void ProfilerFPS::GetSectionsFps(FpsInfoProfiler &fpsInfoResult) const
169 {
170     int msCount = 0;
171     long long msJiange = 100000000;
172     long long msStartTime = (fpsInfoResult.currTimeStamps[0] / msClear) * msClear + msJiange;
173     long long currLastTime = lastCurrTime;
174     long long harTime = 100;
175     int printCount = 0;
176     uint32_t count = 0;
177     for (uint32_t i = 0; i < fpsInfoResult.currTimeStamps.size(); i++) {
178         long long currTime = fpsInfoResult.currTimeStamps[i];
179         if (currTime <= msStartTime) {
180             msCount++;
181         } else if (currTime > msStartTime && currTime <= (msStartTime + msJiange)) {
182             printf("sectionsFps:%d|%lld\n", msCount * ten, currLastTime);
183             msCount = 1;
184             msStartTime += msJiange;
185             currLastTime += harTime;
186             printCount++;
187         } else {
188             printf("sectionsFps:%d|%lld\n", msCount * ten, currLastTime);
189             printCount++;
190             msCount = 0;
191             msStartTime += msJiange;
192             currLastTime += harTime;
193             count--;
194         }
195         long long size = fpsInfoResult.currTimeStamps.size();
196         if (size <= 1) {
197             return;
198         }
199         if (i == (size - 1)) {
200             printf("sectionsFps:%d|%lld\n", msCount * ten, currLastTime);
201             printCount++;
202             GetSectionsPrint(printCount, currLastTime);
203         }
204         count++;
205     }
206 }
207 
GetFPS(std::vector<std::string> v)208 void ProfilerFPS::GetFPS(std::vector<std::string> v)
209 {
210     if (v[number] == "") {
211         printf("the args of num must be not-null!\n");
212     } else {
213         this->num = atoi(v[number].c_str());
214         if (this->num < 0) {
215             printf("set num:%d not valid arg\n", this->num);
216         }
217         printf("set num:%d success\n", this->num);
218         int sectionsNum = atoi(v[four].c_str());
219         for (int i = 0; i < this->num; i++) {
220             GetResultFPS(sectionsNum);
221         }
222     }
223     printf("SP_daemon exec finished!\n");
224 }
225 
226 
GetFpsInfo()227 FpsInfoProfiler ProfilerFPS::GetFpsInfo()
228 {
229     fpsInfoMax.fps = 0;
230     std::string uniteLayer = "UniRender";
231     if (pkgName.empty()) {
232         GetCurrentTime(fifty);
233         fpsInfoMax = GetSurfaceFrame(uniteLayer);
234     } else {
235         bool onTop = IsForeGround();
236         if (onTop) {
237             LOGI("ProfilerFPS.onTop===========");
238             GetCurrentTime(fifty);
239             fpsInfoMax = GetSurfaceFrame(uniteLayer);
240         } else {
241             fpsInfoMax.Clear();
242         }
243     }
244     return fpsInfoMax;
245 }
246 
GetSurfaceFrame(std::string name)247 FpsInfoProfiler ProfilerFPS::GetSurfaceFrame(std::string name)
248 {
249     if (name == "") {
250         return FpsInfoProfiler();
251     }
252     static std::map<std::string, FpsInfoProfiler> fpsMap;
253     if (fpsMap.count(name) == 0) {
254         FpsInfoProfiler tmp;
255         tmp.fps = 0;
256         fpsMap[name] = tmp;
257     }
258     fpsInfo = fpsMap[name];
259     fpsInfo.fps = 0;
260     FILE *fp;
261     static char tmp[1024];
262     GetTimeDiff();
263     std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
264     fp = popen(cmd.c_str(), "r");
265     if (fp == nullptr) {
266         return fpsInfo;
267     }
268     fpsNum = 0;
269     refresh = true;
270     lastTime = -1;
271     LOGI("ProfilerFPS dump time: start!");
272     struct timespec time1 = { 0 };
273     clock_gettime(CLOCK_MONOTONIC, &time1);
274     fpsInfo.curTime = static_cast<int>(time1.tv_sec - 1);
275     fpsInfo.currTimeDump = (time1.tv_sec - 1) * mod + time1.tv_nsec;
276     LOGI("ProfilerFPS Time-------fpsInfo.curTime: %s", std::to_string(fpsInfo.curTime).c_str());
277     while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
278         std::string str(tmp);
279         LOGD("ProfilerFPS dump time: %s", str.c_str());
280         frameReadyTime = 0;
281         std::stringstream sstream;
282         sstream << tmp;
283         sstream >> frameReadyTime;
284         if (frameReadyTime == 0) {
285             continue;
286         }
287         if (lastReadyTime >= frameReadyTime) {
288             lastReadyTime = -1;
289             continue;
290         }
291         GetSameTimeNums();
292     }
293     pclose(fp);
294     LOGI("ProfilerFPS Time-------fpsNum: %s", std::to_string(fpsNum).c_str());
295     return fpsInfo;
296 }
297 
GetSameTimeNums()298 void ProfilerFPS::GetSameTimeNums()
299 {
300     std::string onScreenTime = std::to_string(frameReadyTime / mod);
301     std::string fpsCurTime = std::to_string(fpsInfo.curTime);
302     if (onScreenTime.find(fpsCurTime) != std::string::npos) {
303         fpsNum++;
304         fpsInfo.currTimeStamps.push_back(frameReadyTime);
305     }
306     fpsInfo.fps = fpsNum;
307     if (onScreenTime == fpsCurTime) {
308         long long jitter;
309         if (lastTime != -1) {
310             jitter = frameReadyTime - lastTime;
311             fpsInfo.jitters.push_back(jitter);
312         } else {
313             if (lastFrameReadyTime != 0) {
314                 jitter = frameReadyTime - lastFrameReadyTime;
315                 fpsInfo.jitters.push_back(jitter);
316             }
317         }
318         lastTime = frameReadyTime;
319         lastFrameReadyTime = frameReadyTime;
320     }
321 }
IsForeGround()322 bool ProfilerFPS::IsForeGround()
323 {
324     const std::string cmd = "hidumper -s WindowManagerService -a -a";
325     char buf[1024] = {'\0'};
326     std::string appLine = "app name [" + pkgName;
327     std::string bundleLine = "bundle name [" + pkgName;
328     isFoundAppName = false;
329     isFoundBundleName = false;
330     FILE *fd = popen(cmd.c_str(), "r");
331     if (fd == nullptr) {
332         return false;
333     }
334     while (fgets(buf, sizeof(buf), fd) != nullptr) {
335         std::string line = buf;
336         if (line.find(appLine) != std::string::npos) {
337             isFoundAppName = true;
338         }
339         if (line.find(bundleLine) != std::string::npos) {
340             isFoundBundleName = true;
341         }
342         if (isFoundAppName || isFoundBundleName) {
343             if (line.find("app state") != std::string::npos) {
344                 bool tag = IsFindForeGround(line);
345                 pclose(fd);
346                 return tag;
347             }
348         }
349     }
350     pclose(fd);
351     return false;
352 }
353 
IsFindForeGround(std::string line) const354 bool ProfilerFPS::IsFindForeGround(std::string line) const
355 {
356     std::string foreGroundTag = line.substr(line.find("#") + 1);
357     if (foreGroundTag.find("FOREGROUND") != std::string::npos) {
358         return true;
359     } else {
360         return false;
361     }
362 }
363 }
364 }