• 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 #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 <unistd.h>
25 #include <sys/time.h>
26 #include "include/profiler_fps.h"
27 #include "include/sp_log.h"
28 #include "include/sp_utils.h"
29 
30 
31 namespace OHOS {
32 namespace SmartPerf {
33 
GetResultFPS(int sectionsNum)34 void ProfilerFPS::GetResultFPS(int sectionsNum)
35 {
36     struct timeval start;
37     struct timeval end;
38     gettimeofday(&start, nullptr);
39     FpsInfoProfiler fpsInfoResult;
40     unsigned long runTime;
41     fpsInfoResult = GetFpsInfo();
42     LOGI("result.fps====: %s", std::to_string(fpsInfoResult.fps).c_str());
43     if (fpsInfoResult.fps == 0) {
44         if (lastCurrTime == 0) {
45             long long msStartTime = ((currRealTime / msClear) * msClear) - msClear;
46             printf("fps:%d|%lld\n", fpsInfoResult.fps, msStartTime / oneSec);
47         } else {
48             printf("fps:%d|%lld\n", fpsInfoResult.fps, lastCurrTime + oneThousand);
49             lastCurrTime = lastCurrTime + oneThousand;
50         }
51     } else {
52         long long two = 2;
53         long long currTime = (fpsInfoResult.currTimeStamps[0] / msClear) * msClear + currTimeDiff;
54         if ((lastCurrTime + two) == (currTime / oneSec)) {
55             fpsInfoResult.fps = 0;
56             printf("fps:%d|%lld\n", fpsInfoResult.fps, lastCurrTime + oneThousand);
57             lastCurrTime = lastCurrTime + oneThousand;
58         } else {
59             if (lastCurrTime < (currTime / oneSec)) {
60                 printf("fps:%d|%lld\n", fpsInfoResult.fps, currTime / oneSec);
61                 lastCurrTime = currTime / oneSec;
62             } else {
63                 printf("fps:%d|%lld\n", fpsInfoResult.fps, lastCurrTime + oneThousand);
64                 lastCurrTime = lastCurrTime + oneThousand;
65             }
66         }
67     }
68     time_t now = time(0);
69     if (now == -1) {
70         LOGI("Failed to get current time.");
71         return;
72     }
73     char* dt = ctime(&now);
74     LOGI("printf time is: %s", dt);
75     if (sectionsNum == ten && fpsInfoResult.fps != 0) {
76         GetSectionsFps(fpsInfoResult);
77     }
78     fflush(stdout);
79     gettimeofday(&end, nullptr);
80     runTime = end.tv_sec * 1e6 - start.tv_sec * 1e6 + end.tv_usec - start.tv_usec;
81     if (runTime < oneSec) {
82         usleep(oneSec - runTime);
83     }
84 }
85 
GetFPS(int argc,std::vector<std::string> v)86 void ProfilerFPS::GetFPS(int argc, std::vector<std::string> v)
87 {
88     int sectionsNum = 0;
89     if (v[number] == "") {
90         printf("the args of num must be not-null!\n");
91     } else {
92         num = atoi(v[number].c_str());
93         if (num < 0) {
94             printf("set num:%d not valid arg\n", num);
95         }
96         printf("set num:%d success\n", num);
97         sectionsNum = atoi(v[four].c_str());
98         for (int i = 0; i < num; i++) {
99             GetResultFPS(sectionsNum);
100         }
101     }
102     printf("SP_daemon exec finished!\n");
103 }
104 
GetSectionsPrint(int printCount,long long msStartTime)105 void ProfilerFPS::GetSectionsPrint(int printCount, long long msStartTime)
106 {
107     long long msJiange = 100;
108     if (printCount < ten) {
109         for (int i = 0; i < ten - printCount; i++) {
110             msStartTime += msJiange;
111             printf("sectionsFps:%d|%lld\n", 0, msStartTime);
112         }
113     }
114 }
115 
GetSectionsFps(FpsInfoProfiler & fpsInfo)116 void ProfilerFPS::GetSectionsFps(FpsInfoProfiler &fpsInfo)
117 {
118     int msCount = 0;
119     long long msJiange = 100000000;
120     long long msStartTime = (fpsInfo.currTimeStamps[0] / msClear) * msClear + msJiange;
121     long long currTime = 0;
122     long long currLastTime = lastCurrTime;
123     long long harTime = 100;
124     int printCount = 0;
125     for (int i = 0; i < fpsInfo.currTimeStamps.size(); i++) {
126         currTime = fpsInfo.currTimeStamps[i];
127         if (currTime <= msStartTime) {
128             msCount++;
129         } else if (currTime > msStartTime && currTime <= (msStartTime + msJiange)) {
130             printf("sectionsFps:%d|%lld\n", msCount * ten, currLastTime);
131             msCount = 1;
132             msStartTime += msJiange;
133             currLastTime += harTime;
134             printCount++;
135         } else {
136             printf("sectionsFps:%d|%lld\n", msCount * ten, currLastTime);
137             printCount++;
138             msCount = 0;
139             msStartTime += msJiange;
140             currLastTime += harTime;
141             i--;
142         }
143         if (i == (fpsInfo.currTimeStamps.size() - 1)) {
144             printf("sectionsFps:%d|%lld\n", msCount * ten, currLastTime);
145             printCount++;
146             GetSectionsPrint(printCount, currLastTime);
147         }
148     }
149 }
150 
GetTimeDiff()151 void ProfilerFPS::GetTimeDiff()
152 {
153     long long clockRealTime = 0;
154     long long clockMonotonicRaw = 0;
155     int two = 2;
156     std::string strRealTime;
157     std::string cmd = "timestamps";
158     FILE *fd = popen(cmd.c_str(), "r");
159     if (fd == nullptr) {
160         return;
161     }
162     char buf[1024] = {'\0'};
163     while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
164         std::string line = buf;
165         std::vector<std::string> params;
166         SPUtils::StrSplit(line, " ", params);
167         if (params[0].find("CLOCK_REALTIME") != std::string::npos && clockRealTime == 0) {
168             strRealTime = params[two];
169             strRealTime.erase(strRealTime.find('.'), 1);
170             clockRealTime = std::stoll(strRealTime);
171             currRealTime = clockRealTime;
172         } else if (params[0].find("CLOCK_MONOTONIC_RAW") != std::string::npos && clockMonotonicRaw == 0) {
173             strRealTime = params[two];
174             strRealTime.erase(strRealTime.find('.'), 1);
175             clockMonotonicRaw = std::stoll(strRealTime);
176         }
177     }
178     pclose(fd);
179     currTimeDiff = clockRealTime - clockMonotonicRaw;
180 }
181 
GetSurface()182 std::string ProfilerFPS::GetSurface()
183 {
184     std::string cmdResult;
185     std::string cmdString1 = "hidumper -s 10 -a sur";
186     std::string cmdString2 = "face | grep sur";
187     std::string cmdString3 = "face";
188     SPUtils::LoadCmd(cmdString1 + cmdString2 + cmdString3, cmdResult);
189     size_t position1 = cmdResult.find("[");
190     size_t position2 = cmdResult.find("]");
191     LOGI("cmdResult==: %s", (cmdResult.substr(position1 + 1, position2 - position1 - 1)).c_str());
192     return cmdResult.substr(position1 + 1, position2 - position1 - 1);
193 }
194 
CutLayerName(std::string layerName)195 std::string ProfilerFPS::CutLayerName(std::string layerName)
196 {
197     std::string subLayerName;
198     size_t twenty = 20;
199     if (layerName.size() > twenty) {
200         subLayerName = layerName.substr(0, twenty);
201     } else {
202         subLayerName = layerName;
203     }
204     return subLayerName;
205 }
206 
GetFpsInfoMax()207 FpsInfoProfiler ProfilerFPS::GetFpsInfoMax()
208 {
209     int fpsValue = 0;
210     if (fpsInfo.fps > uniteFpsInfo.fps) {
211         fpsInfoMax = fpsInfo;
212     } else {
213         fpsInfoMax = uniteFpsInfo;
214     }
215     if (fpsInfoMax.fps < fpsValue) {
216         fpsInfoMax.fps = fpsValue;
217     }
218     if (fpsInfoMax == prevFlagFpsInfo) {
219         LOGI("fpsInfoMax == prevFlagFpsInfo");
220         if (cntFpsInfo == lastFlagFpsInfo) {
221             LOGI("cntFpsInfo == lastFlagFpsInfo");
222             fpsInfoMax.fps = 0;
223             fpsInfoMax.Clear();
224             return fpsInfoMax;
225         } else {
226             LOGI("cntFpsInfo != lastFlagFpsInfo");
227             if ((cntFpsInfo.currTimeStamps.size() > 0 && lastFlagFpsInfo.currTimeStamps.size() > 0) &&
228                 cntFpsInfo.currTimeStamps[0] == lastFlagFpsInfo.currTimeStamps[0]) {
229                 cntFpsInfo.fps = 0;
230                 cntFpsInfo.Clear();
231             } else {
232                 lastFlagFpsInfo = cntFpsInfo;
233             }
234             return cntFpsInfo;
235         }
236     } else {
237         LOGI("fpsInfoMax != prevFlagFpsInfo");
238         if ((fpsInfoMax.currTimeStamps.size() > 0 && lastFlagFpsInfo.currTimeStamps.size() > 0) &&
239             fpsInfoMax.currTimeStamps[0] == lastFlagFpsInfo.currTimeStamps[0]) {
240             LOGI("fpsInfoMax == lastFlagFpsInfo");
241             lastFlagFpsInfo = cntFpsInfo;
242             prevFlagFpsInfo = fpsInfoMax;
243             return cntFpsInfo;
244         } else if ((fpsInfoMax.currTimeStamps.size() > 0 && prevFlagFpsInfo.currTimeStamps.size() > 0) &&
245             fpsInfoMax.currTimeStamps[0] == prevFlagFpsInfo.currTimeStamps[0]) {
246             prevFlagFpsInfo = fpsInfoMax;
247             fpsInfoMax.fps = 0;
248             fpsInfoMax.Clear();
249             return fpsInfoMax;
250         } else {
251             LOGI("fpsInfoMax != lastFlagFpsInfo");
252             prevFlagFpsInfo = fpsInfoMax;
253             return fpsInfoMax;
254         }
255     }
256 }
GetFpsInfo()257 FpsInfoProfiler ProfilerFPS::GetFpsInfo()
258 {
259     fpsInfoMax.fps = 0;
260     std::string tempLayerName;
261     std::string uniteLayer = "DisplayNode";
262     uniteLayer = GetSurface();
263     tempLayerName = GetLayer();
264     GetTimeDiff();
265     uniteFpsInfo = GetSurfaceFrame(uniteLayer);
266     fpsInfo = GetSurfaceFrame(tempLayerName);
267     return GetFpsInfoMax();
268 }
269 
GetFpsInfoResult(FpsInfoProfiler & fpsInfo,long long & lastLineTime)270 FpsInfoProfiler ProfilerFPS::GetFpsInfoResult(FpsInfoProfiler &fpsInfo, long long &lastLineTime)
271 {
272     const int maxZeroNum = 266;
273     if (zeroNum >= maxZeroNum) {
274         LOGI("zeroNum====: %s", std::to_string(zeroNum).c_str());
275         while (!(fpsInfo.timeStampQ.empty())) {
276             fpsInfo.timeStampQ.pop();
277         }
278         fpsInfo.fps = 0;
279         fpsInfo.jitters.clear();
280         LOGI("fpsInfo.fps0: %s", std::to_string(fpsInfo.fps).c_str());
281         return fpsInfo;
282     }
283     const int minPrintLine = 5;
284     if (cnt < minPrintLine) {
285         fpsInfo.fps = fpsInfo.preFps;
286         LOGI("fpsInfo.fps1: %s", std::to_string(fpsInfo.fps).c_str());
287         return fpsInfo;
288     }
289     if (!fpsInfo.timeStampQ.empty() && fpsInfo.timeStampQ.back() == lastLineTime) {
290         fpsInfo.fps = fpsGb;
291         if (fpsGb == 0) {
292             fpsInfo.jitters.clear();
293         }
294         LOGI("fpsInfo.fps2: %s", std::to_string(fpsInfo.fps).c_str());
295         LOGI("lastLineTime: %s", std::to_string(lastLineTime).c_str());
296         return fpsInfo;
297     }
298     if (fpsGb > 0) {
299         fpsInfo.fps = fpsGb;
300         fpsInfo.preFps = fpsGb;
301         LOGI("fpsInfo.fps3: %s", std::to_string(fpsInfo.fps).c_str());
302         LOGI("fpsInfo.preFps3: %s", std::to_string(fpsInfo.preFps).c_str());
303         return fpsInfo;
304     } else if (refresh && !jump) {
305         fpsInfo.fps = fpsInfo.preFps;
306         LOGI("fpsInfo.fps4: %s", std::to_string(fpsInfo.fps).c_str());
307         return fpsInfo;
308     } else {
309         fpsInfo.fps = 0;
310         fpsInfo.jitters.clear();
311         LOGI("fpsInfo.fps5: %s", std::to_string(fpsInfo.fps).c_str());
312         return fpsInfo;
313     }
314 }
315 
GetLastFpsInfo(FpsInfoProfiler & fpsInfo)316 void ProfilerFPS::GetLastFpsInfo(FpsInfoProfiler &fpsInfo)
317 {
318     int total = 266;
319     if (cnt == total) {
320         LOGI("cnt == total && fpsGb != 0");
321         lastReadyTime = frameReadyTime;
322         int fpsTmp = 0;
323         cntFpsInfo.jitters.clear();
324         cntFpsInfo.currTimeStamps.clear();
325         while (!(fpsInfo.timeStampQ).empty()) {
326             fpsTmp++;
327             long long currFrame = (fpsInfo.timeStampQ.front());
328             cntFpsInfo.currTimeStamps.push_back(currFrame);
329             if (lastFrame != -1) {
330                 long long jitter = currFrame - lastFrame;
331                 cntFpsInfo.jitters.push_back(jitter);
332             } else {
333                 long long jitter = currFrame - currFrame / mod * mod;
334                 cntFpsInfo.jitters.push_back(jitter);
335             }
336             lastFrame = currFrame;
337             (fpsInfo.timeStampQ).pop();
338         }
339         cntFpsInfo.fps = fpsTmp;
340         LOGI("cntFpsInfo.fps====: %s", std::to_string(cntFpsInfo.fps).c_str());
341     }
342 }
343 
GetPrevFpsInfo(FpsInfoProfiler & fpsInfo)344 void ProfilerFPS::GetPrevFpsInfo(FpsInfoProfiler &fpsInfo)
345 {
346     refresh = true;
347     long long tFrameReadyTime = frameReadyTime / mod;
348     long long tLastReadyTime = lastReadyTime / mod;
349     lastFrame = -1;
350     if (tFrameReadyTime == tLastReadyTime) {
351         (fpsInfo.timeStampQ).push(frameReadyTime);
352     } else if (tFrameReadyTime >= tLastReadyTime + 1) {
353         jump = true;
354         lastReadyTime = frameReadyTime;
355         int fpsTmp = 0;
356         fpsInfo.jitters.clear();
357         fpsInfo.currTimeStamps.clear();
358         while (!(fpsInfo.timeStampQ).empty()) {
359             fpsTmp++;
360             long long currFrame = (fpsInfo.timeStampQ.front());
361             fpsInfo.currTimeStamps.push_back(currFrame);
362             if (lastFrame != -1) {
363                 long long jitter = currFrame - lastFrame;
364                 fpsInfo.jitters.push_back(jitter);
365             } else {
366                 long long jitter = currFrame - currFrame / mod * mod;
367                 fpsInfo.jitters.push_back(jitter);
368             }
369             lastFrame = currFrame;
370             (fpsInfo.timeStampQ).pop();
371         }
372         fpsGb = fpsTmp;
373         LOGI("fpsGb====: %s", std::to_string(fpsGb).c_str());
374         (fpsInfo.timeStampQ).push(frameReadyTime);
375         fpsInfo.lastFrameReadyTime = lastFrame;
376     }
377 }
378 
InitParams(FpsInfoProfiler & fpsInfo,long long & lastLineTime)379 void ProfilerFPS::InitParams(FpsInfoProfiler &fpsInfo, long long &lastLineTime)
380 {
381     lastReadyTime = -1;
382     fpsGb = 0;
383     if (!(fpsInfo.timeStampQ).empty()) {
384         lastReadyTime = (fpsInfo.timeStampQ).back();
385         lastLineTime = (fpsInfo.timeStampQ).back();
386     }
387     jump = false;
388     refresh = false;
389     cnt = 0;
390     zeroNum = 0;
391 }
392 
GetSurfaceFrame(std::string name)393 FpsInfoProfiler ProfilerFPS::GetSurfaceFrame(std::string name)
394 {
395     if (name == "") {
396         return FpsInfoProfiler();
397     }
398     static std::map<std::string, FpsInfoProfiler> fpsMap;
399     if (fpsMap.count(name) == 0) {
400         FpsInfoProfiler tmp;
401         tmp.fps = 0;
402         tmp.preFps = 0;
403         fpsMap[name] = tmp;
404     }
405     fpsInfo = fpsMap[name];
406     fpsInfo.fps = 0;
407     FILE *fp;
408     static char tmp[1024];
409     std::string cmd = "hidumper -s 10 -a \"fps " + name + "\"";
410     LOGI("cmd=====: %s", cmd.c_str());
411     fp = popen(cmd.c_str(), "r");
412     if (fp == nullptr) {
413         return fpsInfo;
414     }
415     static long long lastLineTime;
416     InitParams(fpsInfo, lastLineTime);
417     LOGI("dump time: start!");
418     while (fgets(tmp, sizeof(tmp), fp) != nullptr) {
419         std::string str(tmp);
420         LOGD("dump time: %s", str.c_str());
421         frameReadyTime = 0;
422         std::stringstream sstream;
423         sstream << tmp;
424         sstream >> frameReadyTime;
425         cnt++;
426         if (frameReadyTime == 0) {
427             zeroNum++;
428             continue;
429         }
430         if (lastReadyTime >= frameReadyTime) {
431             lastReadyTime = -1;
432             continue;
433         }
434         GetPrevFpsInfo(fpsInfo);
435         GetLastFpsInfo(fpsInfo);
436     }
437     pclose(fp);
438     return GetFpsInfoResult(fpsInfo, lastLineTime);
439 }
440 
GetLayer()441 std::string ProfilerFPS::GetLayer()
442 {
443     std::vector<DumpEntityProfiler> dumpEntityList;
444     std::string curFocusId = "-1";
445     const std::string cmd = "hidumper -s WindowManagerService -a -a";
446     std::string focusWindowName = "NA";
447     FILE *fd = popen(cmd.c_str(), "r");
448     if (fd == nullptr) {
449         return focusWindowName;
450     }
451     int lineNum = 0;
452     char buf[1024] = {'\0'};
453     while ((fgets(buf, sizeof(buf), fd)) != nullptr) {
454         std::string line = buf;
455         if (line[0] == '-' || line[0] == ' ') {
456             continue;
457         }
458         std::vector<std::string> params;
459         SPUtils::StrSplit(line, " ", params);
460         if (params[windowNameIndex].find("WindowName") != std::string::npos &&
461             params[windowIdIndex].find("WinId") != std::string::npos) {
462             continue;
463         }
464         if (params.size() > paramFourteen) {
465             DumpEntityProfiler dumpEntity { params[0], params[1], params[2], params[3], params[7]};
466             dumpEntityList.push_back(dumpEntity);
467         }
468         if (params.size() == paramFourteen || params.size() == paramTwentyFour) {
469             DumpEntityProfiler dumpEntity { params[0], params[2], params[2], params[3], params[6]};
470             dumpEntityList.push_back(dumpEntity);
471         }
472         if (params.size() == paramThree) {
473             curFocusId = params[focusNameIndex];
474             break;
475         }
476         lineNum++;
477     }
478     pclose(fd);
479     int curId = std::stoi(curFocusId);
480     for (size_t i = 0; i < dumpEntityList.size(); i++) {
481         DumpEntityProfiler dumpItem = dumpEntityList[i];
482         int curWinId = std::stoi(dumpItem.windId);
483         if (curId == curWinId) {
484             focusWindowName = dumpItem.windowName;
485         }
486     }
487     return focusWindowName;
488 }
489 }
490 }