• 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         LOGD("no app list Dynamic"); //没有APP list泳道
104         frameLossRate = swiperDynamicExists ? swiperFrameLossRate :
105                         tabsDynamicExists ? tabsFrameLossRate : -1;
106     } else if (!swiperDynamicExists) {
107         LOGD("no swiper Dynamic"); //没有swiper 泳道
108         frameLossRate = appListDynamicExists ? appFrameLossRate :
109                         tabsDynamicExists ? tabsFrameLossRate : -1;
110     } else if (!tabsDynamicExists) {
111         LOGD("no tabs Dynamic"); //没有tabs 泳道
112         frameLossRate = appListDynamicExists ? appFrameLossRate :
113                         swiperDynamicExists ? swiperFrameLossRate : -1;
114     } else {
115         frameLossRate = -1;
116     }
117 }
118 
MultiLaneFrameRate()119 void StallingRateTrace::MultiLaneFrameRate()
120 {
121     if (appFrameLossRate == 0) {
122         if (swiperFrameLossRate > 0) {
123             LOGD("no app list hitchTime"); //没有app list卡顿次数
124             frameLossRate = swiperFrameLossRate;
125         } else if (tabsFrameLossRate > 0) {
126             frameLossRate = tabsFrameLossRate;
127         } else {
128             frameLossRate = 0;
129         }
130     } else if (swiperFrameLossRate == 0) {
131         LOGD("no swiper list hitchTime"); //没有swiper list卡顿次数
132         if (appFrameLossRate > 0) {
133             frameLossRate = appFrameLossRate;
134         } else if (tabsFrameLossRate > 0) {
135             frameLossRate = tabsFrameLossRate;
136         } else {
137             frameLossRate = 0;
138         }
139     } else if (tabsFrameLossRate == 0) {
140         LOGD("no tabs list hitchTime"); //没有tabs list卡顿次数
141         if (appFrameLossRate > 0) {
142             frameLossRate = appFrameLossRate;
143         } else if (swiperFrameLossRate > 0) {
144             frameLossRate = swiperFrameLossRate;
145         }
146     }
147     AddMultiLaneFrameRate();
148 }
149 
AddMultiLaneFrameRate()150 void StallingRateTrace::AddMultiLaneFrameRate()
151 {
152     if (appFrameLossRate > 0 && swiperFrameLossRate > 0) {
153         //app and swiper hitchTime 1
154         if (appListDynamicStartTime < swiperDynamicStartTime) {
155             frameLossRate = appFrameLossRate;
156         } else {
157             frameLossRate = swiperFrameLossRate;
158         }
159     } else if (appFrameLossRate > 0 && tabsFrameLossRate > 0) {
160         //app and tabs hitchTime 2
161         if (appListDynamicStartTime < appTabsDynamicStartTime) {
162             frameLossRate = appFrameLossRate;
163         } else {
164             frameLossRate = appTabsDynamicStartTime;
165         }
166     } else if (tabsFrameLossRate > 0 && swiperFrameLossRate > 0) {
167         //tabs and swiper hitchTime 3
168         if (appTabsDynamicStartTime < swiperDynamicStartTime) {
169             frameLossRate = tabsFrameLossRate;
170         } else {
171             frameLossRate = swiperFrameLossRate;
172         }
173     }
174 }
175 
176 
AppList(const std::string & line,const std::string & signS,const std::string & signF)177 void StallingRateTrace::AppList(const std::string &line, const std::string &signS, const std::string &signF)
178 {
179     if (IsAppLaunchPatternMatched(line)) {
180         if (listFlag) {
181             appListDynamicFinishTime = GetTimes(line, signF);
182             LOGD("AppList line start: (%s), appListDynamicFinishTime: (%s)",
183                 line.c_str(), std::to_string(appListDynamicFinishTime).c_str());
184             listFlag = false;
185         } else {
186             appListDynamicStartTime = GetTimes(line, signS);
187             LOGD("AppList line finish: (%s), appListDynamicStartTime: (%s)",
188                 line.c_str(), std::to_string(appListDynamicStartTime).c_str());
189             listFlag = true;
190             frameLossTime = 0;
191         }
192     }
193     if (listFlag) {
194         GetRsHardWareRate(nowFrameRate, line, SWIM_APPLIST);
195         if (upperScreenFlag) {
196             if (line.find("|H:Present Fence ") != std::string::npos) {
197                 fenceId = GetFenceId(line);
198                 LOGD("fenceID:(%d)", fenceId);
199             }
200             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceId);
201             if (line.find(waitFenceId) != std::string::npos) {
202                 nowTime = SPUtilesTye::StringToSometype<double>(StallingRateTrace::GetOnScreenTimeStart(line));
203                 GetFrameLossTime(nowTime, lastTime, roundTime, frameLossTime);
204                 LOGD("frameLossTime: (%s)", std::to_string(frameLossTime).c_str());
205                 lastTime = nowTime;
206                 upperScreenFlag = false;
207             }
208         }
209     }
210 }
211 
GetFrameLossTime(double & curTime,double & prevTime,double & drawTime,double & totalFrameLossTime)212 void StallingRateTrace::GetFrameLossTime(double &curTime, double &prevTime,
213     double &drawTime, double &totalFrameLossTime)
214 {
215     if ((curTime - prevTime) > drawTime && prevTime != 0) {
216         double diffTime = (curTime - prevTime) - drawTime;
217         totalFrameLossTime += diffTime;
218         LOGD("diffTime: (%s), totalFrameLossTime: (%s)",
219             std::to_string(diffTime).c_str(), std::to_string(totalFrameLossTime).c_str());
220     }
221 }
222 
GetRsHardWareRate(double curFrameRate,const std::string & line,SWIM_TYPE type)223 void StallingRateTrace::GetRsHardWareRate(double curFrameRate, const std::string &line, SWIM_TYPE type)
224 {
225     if (line.find("H:RSHardwareThread::CommitAndReleaseLayers") != std::string::npos) {
226         switch (type) {
227             case SWIM_APPLIST:
228                 upperScreenFlag = true;
229                 break;
230             case SWIM_APPSWIPER:
231                 upperScreenSwiperFlag = true;
232                 break;
233             case SWIM_APPTABS:
234                 upperScreenTabsFlag = true;
235                 break;
236             default:
237                 break;
238         }
239         curFrameRate = GetFrameRate(line);
240         if (curFrameRate != 0) {
241             UpdateRoundTime(curFrameRate, type);
242         }
243     } else if (line.find("H:RSHardwareThread::PerformSetActiveMode setting active mode") != std::string::npos) {
244         switch (type) {
245             case SWIM_APPLIST:
246                 upperScreenFlag = true;
247                 break;
248             case SWIM_APPSWIPER:
249                 upperScreenSwiperFlag = true;
250                 break;
251             case SWIM_APPTABS:
252                 upperScreenTabsFlag = true;
253                 break;
254             default:
255                 break;
256         }
257         curFrameRate = GetFrameRate(line);
258         if (curFrameRate != 0) {
259             UpdateRoundTime(curFrameRate, type);
260         }
261     }
262 }
263 
UpdateRoundTime(double curFrameRate,SWIM_TYPE type)264 void StallingRateTrace::UpdateRoundTime(double curFrameRate, SWIM_TYPE type)
265 {
266     const double kadunNum = 1.5;
267     const double num = 1;
268     if (curFrameRate != 0) {
269         switch (type) {
270             case SWIM_APPLIST:
271                 roundTime = (num / curFrameRate) * kadunNum;
272                 break;
273             case SWIM_APPSWIPER:
274                 roundSwiperTime = (num / curFrameRate) * kadunNum;
275                 break;
276             case SWIM_APPTABS:
277                 roundTabsTime = (num / curFrameRate) * kadunNum;
278                 break;
279             default:
280                 break;
281         }
282     }
283 }
284 
AppSwiperScroll(const std::string & line,const std::string & signS,const std::string & signF)285 void StallingRateTrace::AppSwiperScroll(const std::string &line, const std::string &signS, const std::string &signF)
286 {
287     if (IsAppLaunchPatternMatched(line)) {
288         if (swiperScrollFlag == 0) {
289             swiperDynamicStartTime = GetTimes(line, signS);
290             LOGD("AppSwiperScroll line start: (%s), swiperDynamicStartTime: (%s)",
291                 line.c_str(), std::to_string(swiperDynamicStartTime).c_str());
292             frameLossSwiperTime = 0;
293             swiperScrollFlag = 1;
294             swiperFlag = true;
295         }
296     }
297     if (IsAppLaunchPatternMatched(line)) {
298         if (swiperFlingFlag == 1) {
299             swiperDynamicFinishTime = GetTimes(line, signF);
300             LOGD("AppSwiper FinishTime line: (%s), swiperDynamicFinishTime: (%s)",
301                 line.c_str(), std::to_string(swiperDynamicFinishTime).c_str());
302             swiperFlag = false;
303         }
304         if (swiperDynamicFinishTime == 0) {
305             swiperFlingFlag = 0;
306         }
307         swiperFlingFlag++;
308     }
309     if (swiperFlag) {
310         GetRsHardWareRate(nowSwiperFrameRate, line, SWIM_APPSWIPER);
311         if (upperScreenSwiperFlag) {
312             if (line.find("|H:Present Fence ") != std::string::npos) {
313                 fenceIdSwiper = GetFenceId(line);
314             }
315             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceIdSwiper);
316             if (line.find(waitFenceId) != std::string::npos) {
317                 nowSwiperTime = SPUtilesTye::StringToSometype<double>(StallingRateTrace::GetOnScreenTimeStart(line));
318                 GetFrameLossTime(nowSwiperTime, lastSwiperTime, roundSwiperTime, frameLossSwiperTime);
319                 LOGD("nowSwiperTime: (%s), frameLossSwiperTime: (%s)",
320                     std::to_string(nowSwiperTime).c_str(), std::to_string(frameLossSwiperTime).c_str());
321                 lastSwiperTime = nowSwiperTime;
322                 upperScreenSwiperFlag = false;
323             }
324         }
325     }
326 }
327 
APPTabs(const std::string & line,const std::string & signS,const std::string & signF)328 void StallingRateTrace::APPTabs(const std::string &line, const std::string &signS, const std::string &signF)
329 {
330     if (IsAppLaunchPatternMatched(line)) {
331         if (tabsFlag) {
332             appTabsDynamicFinishTime = GetTimes(line, signF);
333             LOGD("APPTabs line start: (%s), appTabsDynamicFinishTime: (%s)",
334                 line.c_str(), std::to_string(appTabsDynamicFinishTime).c_str());
335             tabsFlag = false;
336         } else {
337             appTabsDynamicStartTime = GetTimes(line, signS);
338             LOGD("APPTabs line finish: (%s), appTabsDynamicStartTime: (%s)",
339                 line.c_str(), std::to_string(appTabsDynamicStartTime).c_str());
340             tabsFlag = true;
341             frameLossTabsTime = 0;
342         }
343     }
344     if (tabsFlag) {
345         GetRsHardWareRate(nowTabsFrameRate, line, SWIM_APPTABS);
346         if (upperScreenTabsFlag) {
347             if (line.find("|H:Present Fence ") != std::string::npos) {
348                 fenceIdTabs = GetFenceId(line);
349             }
350             std::string waitFenceId = "|H:Waiting for Present Fence " + std::to_string(fenceIdTabs);
351             if (line.find(waitFenceId) != std::string::npos) {
352                 nowTabsTime = SPUtilesTye::StringToSometype<double>(GetOnScreenTimeStart(line));
353                 GetFrameLossTime(nowTabsTime, lastTabsTime, roundTabsTime, frameLossTabsTime);
354                 lastTabsTime = nowTabsTime;
355                 upperScreenTabsFlag = false;
356             }
357         }
358     }
359 }
360 
GetFrameRate(const std::string & line) const361 double StallingRateTrace::GetFrameRate(const std::string &line) const
362 {
363     double rate = 0;
364     std::string delimiter = "rate: ";
365     if (line.find("now:") != std::string::npos && line.find("rate:") != std::string::npos) {
366         std::string delimiter1 = ", now:";
367         size_t pos1 = line.find(delimiter);
368         std::string result1 = line.substr(pos1 + delimiter.length());
369         size_t pos2 = line.find(delimiter1);
370         std::string result2 = result1.substr(0, pos2);
371         rate = SPUtilesTye::StringToSometype<double>(result2.c_str());
372     }
373     if (line.find("rate:") != std::string::npos) {
374         size_t pos = line.find(delimiter);
375         std::string result = line.substr(pos + delimiter.length());
376         rate = SPUtilesTye::StringToSometype<double>(result.c_str());
377     }
378     return rate;
379 }
380 
GetFenceId(const std::string & line) const381 int StallingRateTrace::GetFenceId(const std::string &line) const
382 {
383     std::string delimiter = "H:Present Fence ";
384     size_t pos = line.find(delimiter);
385     std::string result = line.substr(pos + delimiter.length());
386     int presentFenceId = SPUtilesTye::StringToSometype<int>(result.c_str());
387     return presentFenceId;
388 }
389 
GetOnScreenTimeStart(const std::string & line) const390 std::string StallingRateTrace::GetOnScreenTimeStart(const std::string &line) const
391 {
392     std::string startTime = "0";
393     size_t subNum = 7;
394     size_t positionFirst = line.find("....");
395     size_t positionSecond = line.find(":");
396     startTime = line.substr(positionFirst + subNum, positionSecond - positionFirst - subNum);
397     return startTime;
398 }
399 
GetTimes(const std::string & line,const std::string & sign) const400 double StallingRateTrace::GetTimes(const std::string &line, const std::string &sign) const
401 {
402     size_t positionFirst = line.find("....");
403     size_t positionSecond = line.find(":");
404     if (positionFirst != std::string::npos && positionSecond != std::string::npos) {
405         if (line.find(sign) != std::string::npos) {
406             size_t subNum = 7;
407             return SPUtilesTye::StringToSometype<double>(line.substr(
408                 positionFirst + subNum, positionSecond - positionFirst - subNum));
409         }
410     }
411     return 0.0;
412 }
IsAppLaunchPatternMatched(const std::string & line)413 bool StallingRateTrace::IsAppLaunchPatternMatched(const std::string &line)
414 {
415     static const std::unordered_set<std::string> appLaunchPatterns = {
416         "H:LAUNCHER_APP_LAUNCH_FROM_ICON,",
417         "H:APP_LIST_FLING,",
418         "H:WEB_LIST_FLING",
419         "H:ABILITY_OR_PAGE_SWITCH,",
420         "H:APP_TRANSITION_TO_OTHER_APP,",
421         "H:LAUNCHER_APP_LAUNCH_FROM_DOCK,",
422         "H:LAUNCHER_APP_LAUNCH_FROM_APPCENTER,",
423         "H:APP_SWIPER_NO_ANIMATION_SWITCH",
424         "H:APP_SWITCH_FRAME_ANIMATION",
425         "H:APP_SWIPER_SCROLL,",
426         "H:APP_SWIPER_FLING,",
427         "H:APP_TABS_NO_ANIMATION_SWITCH",
428         "H:APP_TABS_FRAME_ANIMATION",
429         "H:APP_TABS_SCROLL,"
430     };
431     for (const auto &keyWords : appLaunchPatterns) {
432         size_t pos = line.find(keyWords);
433         if (pos != std::string::npos) {
434             if (pos > 0 && isspace(line[pos - 1])) {
435                 continue;
436             }
437             if (pos + keyWords.length() < line.length() && !isspace(line[pos + keyWords.length()]) &&
438             line[pos + keyWords.length()] != ',') {
439                 continue;
440             }
441             if (pos + keyWords.length() < line.length() && (line[pos + keyWords.length()] == ',')) {
442                 return false;
443             }
444             LOGD("StallingRateTrace::IsAppLaunchPatternMatched: (%s)", keyWords.c_str());
445             return true;
446         }
447     }
448     return false;
449 }
450 }
451 }
452