14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 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 <iomanip> 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/runtime_call_id.h" 194514f5e3Sopenharmony_ci 204514f5e3Sopenharmony_cinamespace panda::ecmascript { 214514f5e3Sopenharmony_ci// NOLINTNEXTLINE(modernize-avoid-c-arrays) 224514f5e3Sopenharmony_ciEcmaRuntimeStat::EcmaRuntimeStat(const char *const runtimeCallerNames[], int count) 234514f5e3Sopenharmony_ci{ 244514f5e3Sopenharmony_ci for (int i = 0; i < count; i++) { 254514f5e3Sopenharmony_ci // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) 264514f5e3Sopenharmony_ci callerStat_.emplace_back(PandaRuntimeCallerStat(CString(runtimeCallerNames[i]))); 274514f5e3Sopenharmony_ci } 284514f5e3Sopenharmony_ci} 294514f5e3Sopenharmony_ci 304514f5e3Sopenharmony_civoid EcmaRuntimeStat::StartCount(PandaRuntimeTimer *timer, int callerId) 314514f5e3Sopenharmony_ci{ 324514f5e3Sopenharmony_ci if (currentTimer_ != nullptr) { 334514f5e3Sopenharmony_ci timer->SetParent(currentTimer_); 344514f5e3Sopenharmony_ci } 354514f5e3Sopenharmony_ci PandaRuntimeTimer *parent = currentTimer_; 364514f5e3Sopenharmony_ci currentTimer_ = timer; 374514f5e3Sopenharmony_ci PandaRuntimeCallerStat *callerStat = &callerStat_[callerId]; 384514f5e3Sopenharmony_ci timer->Start(callerStat, parent); 394514f5e3Sopenharmony_ci} 404514f5e3Sopenharmony_ci 414514f5e3Sopenharmony_civoid EcmaRuntimeStat::StopCount(const PandaRuntimeTimer *nowTimer) 424514f5e3Sopenharmony_ci{ 434514f5e3Sopenharmony_ci if (nowTimer != currentTimer_) { 444514f5e3Sopenharmony_ci return; 454514f5e3Sopenharmony_ci } 464514f5e3Sopenharmony_ci PandaRuntimeTimer *parentTimer = currentTimer_->Stop(); 474514f5e3Sopenharmony_ci currentTimer_ = parentTimer; 484514f5e3Sopenharmony_ci} 494514f5e3Sopenharmony_ci 504514f5e3Sopenharmony_civoid EcmaRuntimeStat::Print() const 514514f5e3Sopenharmony_ci{ 524514f5e3Sopenharmony_ci if (currentTimer_ != nullptr) { 534514f5e3Sopenharmony_ci currentTimer_->Snapshot(); 544514f5e3Sopenharmony_ci } 554514f5e3Sopenharmony_ci PrintAllStats(); 564514f5e3Sopenharmony_ci} 574514f5e3Sopenharmony_ci 584514f5e3Sopenharmony_civoid EcmaRuntimeStat::ResetAllCount() 594514f5e3Sopenharmony_ci{ 604514f5e3Sopenharmony_ci while (currentTimer_ != nullptr) { 614514f5e3Sopenharmony_ci StopCount(currentTimer_); 624514f5e3Sopenharmony_ci } 634514f5e3Sopenharmony_ci for (auto &runCallerStat : callerStat_) { 644514f5e3Sopenharmony_ci runCallerStat.Reset(); 654514f5e3Sopenharmony_ci } 664514f5e3Sopenharmony_ci} 674514f5e3Sopenharmony_ci 684514f5e3Sopenharmony_civoid EcmaRuntimeStat::PrintAllStats() const 694514f5e3Sopenharmony_ci{ 704514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "panda runtime stat:"; 714514f5e3Sopenharmony_ci static constexpr int nameRightAdjustment = 45; 724514f5e3Sopenharmony_ci static constexpr int numberRightAdjustment = 12; 734514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "InterPreter && GC && C++ Builtin Function" 744514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << "Time(ns)" << std::setw(numberRightAdjustment) << "Count" 754514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << "MaxTime(ns)" 764514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << "AvgTime(ns)"; 774514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "============================================================" 784514f5e3Sopenharmony_ci << "========================================================="; 794514f5e3Sopenharmony_ci 804514f5e3Sopenharmony_ci CVector<PandaRuntimeCallerStat> callerStat; 814514f5e3Sopenharmony_ci for (auto &runCallerStat : callerStat_) { 824514f5e3Sopenharmony_ci callerStat.push_back(runCallerStat); 834514f5e3Sopenharmony_ci } 844514f5e3Sopenharmony_ci // Sort by TotalTime 854514f5e3Sopenharmony_ci std::sort(callerStat.begin(), callerStat.end(), 864514f5e3Sopenharmony_ci [](const PandaRuntimeCallerStat &a, const PandaRuntimeCallerStat &b) -> bool { 874514f5e3Sopenharmony_ci return a.TotalTime() > b.TotalTime(); 884514f5e3Sopenharmony_ci }); 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ci uint64_t totalTime = 0; 914514f5e3Sopenharmony_ci uint64_t interpreterTotalTime = 0; 924514f5e3Sopenharmony_ci uint64_t builtinTotalTime = 0; 934514f5e3Sopenharmony_ci uint64_t abstractOperationTotalTime = 0; 944514f5e3Sopenharmony_ci uint64_t memoryTotalTime = 0; 954514f5e3Sopenharmony_ci uint64_t runtimeTotalTime = 0; 964514f5e3Sopenharmony_ci for (auto &runCallerStat : callerStat) { 974514f5e3Sopenharmony_ci if (runCallerStat.TotalCount() != 0) { 984514f5e3Sopenharmony_ci totalTime += runCallerStat.TotalTime(); 994514f5e3Sopenharmony_ci CString header = runCallerStat.GetHeaderOfName(); 1004514f5e3Sopenharmony_ci if (header == CString("Interpreter")) { 1014514f5e3Sopenharmony_ci interpreterTotalTime += runCallerStat.TotalTime(); 1024514f5e3Sopenharmony_ci } else if (header == CString("BuiltinsApi")) { 1034514f5e3Sopenharmony_ci builtinTotalTime += runCallerStat.TotalTime(); 1044514f5e3Sopenharmony_ci } else if (header == CString("AbstractOperation")) { 1054514f5e3Sopenharmony_ci abstractOperationTotalTime += runCallerStat.TotalTime(); 1064514f5e3Sopenharmony_ci } else if (header == CString("Memory")) { 1074514f5e3Sopenharmony_ci memoryTotalTime += runCallerStat.TotalTime(); 1084514f5e3Sopenharmony_ci } else if (header == CString("Runtime")) { 1094514f5e3Sopenharmony_ci runtimeTotalTime += runCallerStat.TotalTime(); 1104514f5e3Sopenharmony_ci } 1114514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << runCallerStat.Name() 1124514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << runCallerStat.TotalTime() 1134514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << runCallerStat.TotalCount() 1144514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << runCallerStat.MaxTime() 1154514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) 1164514f5e3Sopenharmony_ci << runCallerStat.TotalTime() / runCallerStat.TotalCount(); 1174514f5e3Sopenharmony_ci } 1184514f5e3Sopenharmony_ci } 1194514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "------------------------------------------------------------" 1204514f5e3Sopenharmony_ci << "---------------------------------------------------------"; 1214514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Interpreter Total Time(ns)" 1224514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << interpreterTotalTime; 1234514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "BuiltinsApi Total Time(ns)" 1244514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << builtinTotalTime; 1254514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "AbstractOperation Total Time(ns)" 1264514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << abstractOperationTotalTime; 1274514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Memory Total Time(ns)" 1284514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << memoryTotalTime; 1294514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Runtime Total Time(ns)" 1304514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << runtimeTotalTime; 1314514f5e3Sopenharmony_ci LOG_ECMA(INFO) << "------------------------------------------------------------" 1324514f5e3Sopenharmony_ci << "---------------------------------------------------------"; 1334514f5e3Sopenharmony_ci LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Total Time(ns)" 1344514f5e3Sopenharmony_ci << std::setw(numberRightAdjustment) << totalTime; 1354514f5e3Sopenharmony_ci} 1364514f5e3Sopenharmony_ci 1374514f5e3Sopenharmony_ciEcmaRuntimeStatScope::EcmaRuntimeStatScope(EcmaVM *vm) : vm_(vm) 1384514f5e3Sopenharmony_ci{ 1394514f5e3Sopenharmony_ci if (vm_->GetJSOptions().IsEnableRuntimeStat()) { 1404514f5e3Sopenharmony_ci vm_->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(true); 1414514f5e3Sopenharmony_ci } 1424514f5e3Sopenharmony_ci} 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_ciEcmaRuntimeStatScope::~EcmaRuntimeStatScope() 1454514f5e3Sopenharmony_ci{ 1464514f5e3Sopenharmony_ci if (vm_->GetJSOptions().IsEnableRuntimeStat()) { 1474514f5e3Sopenharmony_ci vm_->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(false); 1484514f5e3Sopenharmony_ci } 1494514f5e3Sopenharmony_ci vm_ = nullptr; 1504514f5e3Sopenharmony_ci} 1514514f5e3Sopenharmony_ci} // namespace panda::ecmascript 152