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