14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "ecmascript/dfx/vmstat/function_call_timer.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include <iomanip> 194514f5e3Sopenharmony_ci 204514f5e3Sopenharmony_cinamespace panda::ecmascript { 214514f5e3Sopenharmony_civoid FunctionCallTimer::StartCount(size_t id, bool isAot) 224514f5e3Sopenharmony_ci{ 234514f5e3Sopenharmony_ci PandaRuntimeTimer *callerTimer = currentTimer_; 244514f5e3Sopenharmony_ci auto calleeTimer = &callTimer_[id]; 254514f5e3Sopenharmony_ci if (callerTimer != nullptr) { 264514f5e3Sopenharmony_ci calleeTimer->SetParent(callerTimer); 274514f5e3Sopenharmony_ci } 284514f5e3Sopenharmony_ci currentTimer_ = calleeTimer; 294514f5e3Sopenharmony_ci FunctionCallStat *calleeStat = nullptr; 304514f5e3Sopenharmony_ci if (isAot) { 314514f5e3Sopenharmony_ci calleeStat = &aotCallStat_[id]; 324514f5e3Sopenharmony_ci } else { 334514f5e3Sopenharmony_ci calleeStat = &intCallStat_[id]; 344514f5e3Sopenharmony_ci } 354514f5e3Sopenharmony_ci calleeTimer->Start(calleeStat, callerTimer); 364514f5e3Sopenharmony_ci} 374514f5e3Sopenharmony_ci 384514f5e3Sopenharmony_civoid FunctionCallTimer::StopCount(Method *method) 394514f5e3Sopenharmony_ci{ 404514f5e3Sopenharmony_ci size_t id = method->GetMethodId().GetOffset(); 414514f5e3Sopenharmony_ci auto callee = &callTimer_[id]; 424514f5e3Sopenharmony_ci if (callee != currentTimer_) { 434514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "EndCallTimer and StartCallTimer have different functions. Current function: " 444514f5e3Sopenharmony_ci << GetFullName(method) << "has been skipped"; 454514f5e3Sopenharmony_ci return; 464514f5e3Sopenharmony_ci } 474514f5e3Sopenharmony_ci 484514f5e3Sopenharmony_ci PandaRuntimeTimer *callerTimer = callee->Stop(); 494514f5e3Sopenharmony_ci currentTimer_ = callerTimer; 504514f5e3Sopenharmony_ci} 514514f5e3Sopenharmony_ci 524514f5e3Sopenharmony_ciCString FunctionCallTimer::GetFullName(Method *method) 534514f5e3Sopenharmony_ci{ 544514f5e3Sopenharmony_ci CString funcName(method->GetMethodName()); 554514f5e3Sopenharmony_ci CString recordName = method->GetRecordNameStr(); 564514f5e3Sopenharmony_ci CString fullName = funcName + "@" + recordName; 574514f5e3Sopenharmony_ci return fullName; 584514f5e3Sopenharmony_ci} 594514f5e3Sopenharmony_ci 604514f5e3Sopenharmony_civoid FunctionCallTimer::InitialStatAndTimer(Method *method, size_t methodId, bool isAot) 614514f5e3Sopenharmony_ci{ 624514f5e3Sopenharmony_ci if (isAot) { 634514f5e3Sopenharmony_ci auto iter = aotCallStat_.find(methodId); 644514f5e3Sopenharmony_ci if (iter == aotCallStat_.end()) { 654514f5e3Sopenharmony_ci CString funcName = GetFullName(method); 664514f5e3Sopenharmony_ci FunctionCallStat stat(funcName, isAot); 674514f5e3Sopenharmony_ci aotCallStat_[methodId] = stat; 684514f5e3Sopenharmony_ci } 694514f5e3Sopenharmony_ci } else { 704514f5e3Sopenharmony_ci auto iter = intCallStat_.find(methodId); 714514f5e3Sopenharmony_ci if (iter == intCallStat_.end()) { 724514f5e3Sopenharmony_ci CString funcName = GetFullName(method); 734514f5e3Sopenharmony_ci FunctionCallStat stat(funcName, isAot); 744514f5e3Sopenharmony_ci intCallStat_[methodId] = stat; 754514f5e3Sopenharmony_ci } 764514f5e3Sopenharmony_ci } 774514f5e3Sopenharmony_ci 784514f5e3Sopenharmony_ci PandaRuntimeTimer timer; 794514f5e3Sopenharmony_ci callTimer_[methodId] = timer; 804514f5e3Sopenharmony_ci} 814514f5e3Sopenharmony_ci 824514f5e3Sopenharmony_civoid FunctionCallTimer::PrintAllStats() 834514f5e3Sopenharmony_ci{ 844514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "function call stat:"; 854514f5e3Sopenharmony_ci static constexpr int nameRightAdjustment = 45; 864514f5e3Sopenharmony_ci static constexpr int numberRightAdjustment = 15; 874514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "JS && TS Function Name" 884514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << "Type" 894514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << "Time(ns)" << std::setw(numberRightAdjustment) << "Count" 904514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << "MaxTime(ns)" 914514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << "AvgTime(ns)"; 924514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "=============================================================" 934514f5e3Sopenharmony_ci << "============================================================="; 944514f5e3Sopenharmony_ci 954514f5e3Sopenharmony_ci CVector<FunctionCallStat> callStatVec; 964514f5e3Sopenharmony_ci for (auto &stat : aotCallStat_) { 974514f5e3Sopenharmony_ci callStatVec.emplace_back(stat.second); 984514f5e3Sopenharmony_ci } 994514f5e3Sopenharmony_ci for (auto &stat : intCallStat_) { 1004514f5e3Sopenharmony_ci callStatVec.emplace_back(stat.second); 1014514f5e3Sopenharmony_ci } 1024514f5e3Sopenharmony_ci // Sort by TotalTime 1034514f5e3Sopenharmony_ci std::sort(callStatVec.begin(), callStatVec.end(), 1044514f5e3Sopenharmony_ci [](const FunctionCallStat &a, const FunctionCallStat &b) -> bool { 1054514f5e3Sopenharmony_ci return a.TotalTime() > b.TotalTime(); 1064514f5e3Sopenharmony_ci }); 1074514f5e3Sopenharmony_ci 1084514f5e3Sopenharmony_ci for (auto &stat : callStatVec) { 1094514f5e3Sopenharmony_ci if (stat.TotalCount() != 0) { 1104514f5e3Sopenharmony_ci CString type = stat.IsAot() ? "Aot" : "Interpreter"; 1114514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << stat.Name() 1124514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << type 1134514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << stat.TotalTime() 1144514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << stat.TotalCount() 1154514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << stat.MaxTime() 1164514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << stat.TotalTime() / stat.TotalCount(); 1174514f5e3Sopenharmony_ci } 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci} 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_civoid FunctionCallTimer::ResetStat() 1224514f5e3Sopenharmony_ci{ 1234514f5e3Sopenharmony_ci for (auto &stat : aotCallStat_) { 1244514f5e3Sopenharmony_ci stat.second.Reset(); 1254514f5e3Sopenharmony_ci } 1264514f5e3Sopenharmony_ci 1274514f5e3Sopenharmony_ci for (auto &stat : intCallStat_) { 1284514f5e3Sopenharmony_ci stat.second.Reset(); 1294514f5e3Sopenharmony_ci } 1304514f5e3Sopenharmony_ci} 1314514f5e3Sopenharmony_ci}