• 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 <fstream>
16 #include <string>
17 #include <iostream>
18 #include <regex>
19 #include <cmath>
20 #include <unordered_set>
21 #include "include/stalling_rate_trace.h"
22 #include "include/sp_log.h"
23 #include "include/sp_utils.h"
24 
25 namespace OHOS {
26 namespace SmartPerf {
StallingRateResult(std::string file)27 double StallingRateTrace::StallingRateResult(std::string file)
28 {
29     double stalligRate = 0;
30     char realPath[PATH_MAX] = {0x00};
31     if ((realpath(file.c_str(), realPath) == nullptr)) {
32         std::cout << "" << std::endl;
33     }
34     infile.open(realPath);
35     if (infile.fail()) {
36         LOGE("StallingRateTrace open file(%s) fialed ", file.c_str());
37         return stalligRate;
38     }
39     stalligRate = SmartPerf::StallingRateTrace::CalculateTime();
40     infile.close();
41     return stalligRate;
42 }
43 
CalculateTime()44 double StallingRateTrace::CalculateTime()
45 {
46     frameLossRate = 0;
47     frameLossTime = 0;
48     swiperFrameLossRate = 0;
49     appFrameLossRate = 0;
50     tabsFrameLossRate = 0;
51     frameLossSwiperTime = 0;
52     frameLossTabsTime = 0;
53     std::string signS = "S|";
54     std::string signF = "F|";
55     std::string line;
56     while (getline(infile, line)) {
57         AppList(line, signS, signF);
58         AppSwiperScroll(line, signS, signF);
59         APPTabs(line, signS, signF);
60     }
61     CalcFrameRate();
62     JudgFrameRate();
63     MultiLaneFrameRate();
64     return frameLossRate;
65 }
66 
CalcFrameRate()67 void StallingRateTrace::CalcFrameRate()
68 {
69     if (appListDynamicStartTime != 0 && appListDynamicFinishTime != 0) {
70         appFrameLossRate = (frameLossTime / (appListDynamicFinishTime - appListDynamicStartTime) * oneThousand);
71     } else {
72         appFrameLossRate = -1;
73     }
74 
75     if (swiperDynamicFinishTime != 0 && swiperDynamicStartTime != 0) {
76         swiperFrameLossRate = (frameLossSwiperTime / (swiperDynamicFinishTime - swiperDynamicStartTime) * oneThousand);
77     } else {
78         swiperFrameLossRate = -1;
79     }
80 
81     if (appTabsDynamicStartTime != 0 && appTabsDynamicFinishTime != 0) {
82         tabsFrameLossRate = (frameLossTabsTime / (appTabsDynamicFinishTime - appTabsDynamicStartTime) * oneThousand);
83     } else {
84         tabsFrameLossRate = -1;
85     }
86     LOGD("result.appFrameLossRate: (%s), result.swiperFrameLossRate: (%s), result.tabsFrameLossRate: (%s)",
87         std::to_string(appFrameLossRate).c_str(),
88         std::to_string(swiperFrameLossRate).c_str(),
89         std::to_string(tabsFrameLossRate).c_str());
90 }
91 
JudgFrameRate()92 void StallingRateTrace::JudgFrameRate()
93 {
94     auto hasDynamic = [](bool finishTime, bool startTime) {
95         return finishTime != 0 || startTime != 0;
96     };
97 
98     bool appListDynamicExists = hasDynamic(appListDynamicFinishTime, appListDynamicStartTime);
99     bool swiperDynamicExists = hasDynamic(swiperDynamicFinishTime, swiperDynamicStartTime);
100     bool tabsDynamicExists = hasDynamic(appTabsDynamicFinishTime, appTabsDynamicStartTime);
101 
102     if (!appListDynamicExists) {
103         frameLossRate = swiperDynamicExists ? swiperFrameLossRate :
104                         tabsDynamicExists ? tabsFrameLossRate : -1;
105     } else if (!swiperDynamicExists) {
106         frameLossRate = appListDynamicExists ? appFrameLossRate :
107                         tabsDynamicExists ? tabsFrameLossRate : -1;
108     } else if (!tabsDynamicExists) {
109         frameLossRate = appListDynamicExists ? appFrameLossRate :
110                         swiperDynamicExists ? swiperFrameLossRate : -1;
111     } else {
112         frameLossRate = -1;
113     }
114 }
115 
MultiLaneFrameRate()116 void StallingRateTrace::MultiLaneFrameRate()
117 {
118     if (appFrameLossRate == 0) {
119         if (swiperFrameLossRate > 0) {
120             frameLossRate = swiperFrameLossRate;
121         } else if (tabsFrameLossRate > 0) {
122             frameLossRate = tabsFrameLossRate;
123         } else {
124             frameLossRate = 0;
125         }
126     } else if (swiperFrameLossRate == 0) {
127         if (appFrameLossRate > 0) {
128             frameLossRate = appFrameLossRate;
129         } else if (tabsFrameLossRate > 0) {
130             frameLossRate = tabsFrameLossRate;
131         } else {
132             frameLossRate = 0;
133         }
134     } else if (tabsFrameLossRate == 0) {
135         if (appFrameLossRate > 0) {
136             frameLossRate = appFrameLossRate;
137         } else if (swiperFrameLossRate > 0) {
138             frameLossRate = swiperFrameLossRate;
139         }
140     }
141     AddMultiLaneFrameRate();
142 }
143 
AddMultiLaneFrameRate()144 void StallingRateTrace::AddMultiLaneFrameRate()
145 {
146     if (appFrameLossRate > 0 && swiperFrameLossRate > 0) {
147         //app and swiper hitchTime 1
148         if (appListDynamicStartTime < swiperDynamicStartTime) {
149             frameLossRate = appFrameLossRate;
150         } else {
151             frameLossRate = swiperFrameLossRate;
152         }
153     } else if (appFrameLossRate > 0 && tabsFrameLossRate > 0) {
154         //app and tabs hitchTime 2
155         if (appListDynamicStartTime < appTabsDynamicStartTime) {
156             frameLossRate = appFrameLossRate;
157         } else {
158             frameLossRate = appTabsDynamicStartTime;
159         }
160     } else if (tabsFrameLossRate > 0 && swiperFrameLossRate > 0) {
161         //tabs and swiper hitchTime 3
162         if (appTabsDynamicStartTime < swiperDynamicStartTime) {
163             frameLossRate = tabsFrameLossRate;
164         } else {
165             frameLossRate = swiperFrameLossRate;
166         }
167     }
168 }
169 
170 
AppList(const std::string & line,const std::string & signS,const std::string & signF)171 void StallingRateTrace::AppList(const std::string &line, const std::string &signS, const std::string &signF)
172 {
173     if (IsAppLaunchPatternMatched(line)) {
174         if (listFlag) {
175             appListDynamicFinishTime = GetTimes(line, signF);
176             LOGD("AppList line start: (%s), appListDynamicFinishTime: (%s)",
177                 line.c_str(), std::to_string(appListDynamicFinishTime).c_str());
178             listFlag = false;
179         } else {
180             appListDynamicStartTime = GetTimes(line, signS);
181             LOGD("AppList line finish: (%s), appListDynamicStartTime: (%s)",
182                 line.c_str(), std::to_string(appListDynamicStartTime).c_str());
183             listFlag = true;
184             frameLossTime = 0;
185         }
186     }
187     if (listFlag) {
188         GetRsHardWareRate(nowFrameRate, line, SWIM_APPLIST);
189         if (upperScreenFlag) {
190             if (line.find("|H:Present Fence ") != std::string::npos) {
191                 fenceId = GetFenceId(line);
192             }
193             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceId);
194             if (line.find(waitFenceId) != std::string::npos) {
195                 nowTime = SPUtilesTye::StringToSometype<double>(StallingRateTrace::GetOnScreenTimeStart(line));
196                 GetFrameLossTime(nowTime, lastTime, roundTime, frameLossTime);
197                 LOGD("frameLossTime: (%s)", std::to_string(frameLossTime).c_str());
198                 lastTime = nowTime;
199                 upperScreenFlag = false;
200             }
201         }
202     }
203 }
204 
GetFrameLossTime(double & curTime,double & prevTime,double & drawTime,double & totalFrameLossTime)205 void StallingRateTrace::GetFrameLossTime(double &curTime, double &prevTime,
206     double &drawTime, double &totalFrameLossTime)
207 {
208     if ((curTime - prevTime) > drawTime && prevTime != 0) {
209         double diffTime = (curTime - prevTime) - drawTime;
210         totalFrameLossTime += diffTime;
211         LOGD("diffTime: (%s), totalFrameLossTime: (%s)",
212             std::to_string(diffTime).c_str(), std::to_string(totalFrameLossTime).c_str());
213     }
214 }
215 
GetRsHardWareRate(double curFrameRate,const std::string & line,SWIM_TYPE type)216 void StallingRateTrace::GetRsHardWareRate(double curFrameRate, const std::string &line, SWIM_TYPE type)
217 {
218     if (line.find("H:RSHardwareThread::CommitAndReleaseLayers") != std::string::npos) {
219         switch (type) {
220             case SWIM_APPLIST:
221                 upperScreenFlag = true;
222                 break;
223             case SWIM_APPSWIPER:
224                 upperScreenSwiperFlag = true;
225                 break;
226             case SWIM_APPTABS:
227                 upperScreenTabsFlag = true;
228                 break;
229             default:
230                 break;
231         }
232         curFrameRate = GetFrameRate(line);
233         if (curFrameRate != 0) {
234             UpdateRoundTime(curFrameRate, type);
235         }
236     } else if (line.find("H:RSHardwareThread::PerformSetActiveMode setting active mode") != std::string::npos) {
237         switch (type) {
238             case SWIM_APPLIST:
239                 upperScreenFlag = true;
240                 break;
241             case SWIM_APPSWIPER:
242                 upperScreenSwiperFlag = true;
243                 break;
244             case SWIM_APPTABS:
245                 upperScreenTabsFlag = true;
246                 break;
247             default:
248                 break;
249         }
250         curFrameRate = GetFrameRate(line);
251         if (curFrameRate != 0) {
252             UpdateRoundTime(curFrameRate, type);
253         }
254     }
255 }
256 
UpdateRoundTime(double curFrameRate,SWIM_TYPE type)257 void StallingRateTrace::UpdateRoundTime(double curFrameRate, SWIM_TYPE type)
258 {
259     const double kadunNum = 1.5;
260     const double num = 1;
261     if (curFrameRate != 0) {
262         switch (type) {
263             case SWIM_APPLIST:
264                 roundTime = (num / curFrameRate) * kadunNum;
265                 break;
266             case SWIM_APPSWIPER:
267                 roundSwiperTime = (num / curFrameRate) * kadunNum;
268                 break;
269             case SWIM_APPTABS:
270                 roundTabsTime = (num / curFrameRate) * kadunNum;
271                 break;
272             default:
273                 break;
274         }
275     }
276 }
277 
AppSwiperScroll(const std::string & line,const std::string & signS,const std::string & signF)278 void StallingRateTrace::AppSwiperScroll(const std::string &line, const std::string &signS, const std::string &signF)
279 {
280     if (IsAppLaunchPatternMatched(line)) {
281         if (swiperScrollFlag == 0) {
282             swiperDynamicStartTime = GetTimes(line, signS);
283             LOGD("AppSwiperScroll line start: (%s), swiperDynamicStartTime: (%s)",
284                 line.c_str(), std::to_string(swiperDynamicStartTime).c_str());
285             frameLossSwiperTime = 0;
286             swiperScrollFlag = 1;
287             swiperFlag = true;
288         }
289     }
290     if (IsAppLaunchPatternMatched(line)) {
291         if (swiperFlingFlag == 1) {
292             swiperDynamicFinishTime = GetTimes(line, signF);
293             LOGD("AppSwiper FinishTime line: (%s), swiperDynamicFinishTime: (%s)",
294                 line.c_str(), std::to_string(swiperDynamicFinishTime).c_str());
295             swiperFlag = false;
296         }
297         if (swiperDynamicFinishTime == 0) {
298             swiperFlingFlag = 0;
299         }
300         swiperFlingFlag++;
301     }
302     if (swiperFlag) {
303         GetRsHardWareRate(nowSwiperFrameRate, line, SWIM_APPSWIPER);
304         if (upperScreenSwiperFlag) {
305             if (line.find("|H:Present Fence ") != std::string::npos) {
306                 fenceIdSwiper = GetFenceId(line);
307             }
308             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceIdSwiper);
309             if (line.find(waitFenceId) != std::string::npos) {
310                 nowSwiperTime = SPUtilesTye::StringToSometype<double>(StallingRateTrace::GetOnScreenTimeStart(line));
311                 GetFrameLossTime(nowSwiperTime, lastSwiperTime, roundSwiperTime, frameLossSwiperTime);
312                 LOGD("nowSwiperTime: (%s), frameLossSwiperTime: (%s)",
313                     std::to_string(nowSwiperTime).c_str(), std::to_string(frameLossSwiperTime).c_str());
314                 lastSwiperTime = nowSwiperTime;
315                 upperScreenSwiperFlag = false;
316             }
317         }
318     }
319 }
320 
APPTabs(const std::string & line,const std::string & signS,const std::string & signF)321 void StallingRateTrace::APPTabs(const std::string &line, const std::string &signS, const std::string &signF)
322 {
323     if (IsAppLaunchPatternMatched(line)) {
324         if (tabsFlag) {
325             appTabsDynamicFinishTime = GetTimes(line, signF);
326             LOGD("APPTabs line start: (%s), appTabsDynamicFinishTime: (%s)",
327                 line.c_str(), std::to_string(appTabsDynamicFinishTime).c_str());
328             tabsFlag = false;
329         } else {
330             appTabsDynamicStartTime = GetTimes(line, signS);
331             LOGD("APPTabs line finish: (%s), appTabsDynamicStartTime: (%s)",
332                 line.c_str(), std::to_string(appTabsDynamicStartTime).c_str());
333             tabsFlag = true;
334             frameLossTabsTime = 0;
335         }
336     }
337     if (tabsFlag) {
338         GetRsHardWareRate(nowTabsFrameRate, line, SWIM_APPTABS);
339         if (upperScreenTabsFlag) {
340             if (line.find("|H:Present Fence ") != std::string::npos) {
341                 fenceIdTabs = GetFenceId(line);
342             }
343             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceIdTabs);
344             if (line.find(waitFenceId) != std::string::npos) {
345                 nowTabsTime = std::stod(SmartPerf::StallingRateTrace::GetOnScreenTimeStart(line));
346                 GetFrameLossTime(nowTabsTime, lastTabsTime, roundTabsTime, frameLossTabsTime);
347                 lastTabsTime = nowTabsTime;
348                 upperScreenTabsFlag = false;
349             }
350         }
351     }
352 }
353 
GetFrameRate(const std::string & line) const354 double StallingRateTrace::GetFrameRate(const std::string &line) const
355 {
356     double rate = 0;
357     std::string delimiter = "rate: ";
358     if (line.find("now:") != std::string::npos && line.find("rate:") != std::string::npos) {
359         std::string delimiter1 = ", now:";
360         size_t pos1 = line.find(delimiter);
361         std::string result1 = line.substr(pos1 + delimiter.length());
362         size_t pos2 = line.find(delimiter1);
363         std::string result2 = result1.substr(0, pos2);
364         rate = SPUtilesTye::StringToSometype<double>(result2.c_str());
365     }
366     if (line.find("rate:") != std::string::npos) {
367         size_t pos = line.find(delimiter);
368         std::string result = line.substr(pos + delimiter.length());
369         rate = SPUtilesTye::StringToSometype<double>(result.c_str());
370     }
371     return rate;
372 }
373 
GetFenceId(const std::string & line) const374 int StallingRateTrace::GetFenceId(const std::string &line) const
375 {
376     std::string delimiter = "H:Present Fence ";
377     size_t pos = line.find(delimiter);
378     std::string result = line.substr(pos + delimiter.length());
379     int presentFenceId = SPUtilesTye::StringToSometype<int>(result.c_str());
380     return presentFenceId;
381 }
382 
GetOnScreenTimeStart(const std::string & line) const383 std::string StallingRateTrace::GetOnScreenTimeStart(const std::string &line) const
384 {
385     std::string startTime = "0";
386     size_t subNum = 7;
387     size_t positionFirst = line.find("....");
388     size_t positionSecond = line.find(":");
389     startTime = line.substr(positionFirst + subNum, positionSecond - positionFirst - subNum);
390     return startTime;
391 }
392 
GetTimes(const std::string & line,const std::string & sign) const393 double StallingRateTrace::GetTimes(const std::string &line, const std::string &sign) const
394 {
395     size_t positionFirst = line.find("....");
396     size_t positionSecond = line.find(":");
397     if (positionFirst != std::string::npos && positionSecond != std::string::npos) {
398         if (line.find(sign) != std::string::npos) {
399             size_t subNum = 7;
400             return SPUtilesTye::StringToSometype<double>(line.substr(
401                 positionFirst + subNum, positionSecond - positionFirst - subNum));
402         }
403     }
404     return 0.0;
405 }
IsAppLaunchPatternMatched(const std::string & line)406 bool StallingRateTrace::IsAppLaunchPatternMatched(const std::string &line)
407 {
408     static const std::unordered_set<std::string> appLaunchPatterns = {
409         "H:LAUNCHER_APP_LAUNCH_FROM_ICON,",
410         "H:APP_LIST_FLING,",
411         "H:WEB_LIST_FLING",
412         "H:ABILITY_OR_PAGE_SWITCH,",
413         "H:APP_TRANSITION_TO_OTHER_APP,",
414         "H:LAUNCHER_APP_LAUNCH_FROM_DOCK,",
415         "H:LAUNCHER_APP_LAUNCH_FROM_APPCENTER,",
416         "H:APP_SWIPER_NO_ANIMATION_SWITCH",
417         "H:APP_SWITCH_FRAME_ANIMATION",
418         "H:APP_SWIPER_SCROLL,",
419         "H:APP_SWIPER_FLING,",
420         "H:APP_TABS_NO_ANIMATION_SWITCH",
421         "H:APP_TABS_FRAME_ANIMATION",
422         "H:APP_TABS_SCROLL,"
423     };
424     for (const auto &keyWords : appLaunchPatterns) {
425         size_t pos = line.find(keyWords);
426         if (pos != std::string::npos) {
427             if (pos > 0 && isspace(line[pos - 1])) {
428                 continue;
429             }
430             if (pos + keyWords.length() < line.length() &&
431                 !isspace(line[pos + keyWords.length()]) &&
432                 line[pos + keyWords.length()] != ',') {
433                 continue;
434             }
435             if (pos + keyWords.length() < line.length() && (line[pos + keyWords.length()] == ',')) {
436                 return false;
437             }
438             return true;
439         }
440     }
441     return false;
442 }
443 }
444 }
445