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 23namespace OHOS { 24namespace SmartPerf { 25double 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 42double 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 65void 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 89void 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 116void 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 147void 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 174void 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 215void 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 225void 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 268void 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 289void 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 337void 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 381double 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 401int 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 410std::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 420double 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