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