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