1 /*
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
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
16 #include <iomanip>
17
18 #include "ecmascript/runtime_call_id.h"
19
20 namespace panda::ecmascript {
21 // NOLINTNEXTLINE(modernize-avoid-c-arrays)
EcmaRuntimeStat(const char *const runtimeCallerNames[], int count)22 EcmaRuntimeStat::EcmaRuntimeStat(const char *const runtimeCallerNames[], int count)
23 {
24 for (int i = 0; i < count; i++) {
25 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
26 callerStat_.emplace_back(PandaRuntimeCallerStat(CString(runtimeCallerNames[i])));
27 }
28 }
29
StartCount(PandaRuntimeTimer *timer, int callerId)30 void EcmaRuntimeStat::StartCount(PandaRuntimeTimer *timer, int callerId)
31 {
32 if (currentTimer_ != nullptr) {
33 timer->SetParent(currentTimer_);
34 }
35 PandaRuntimeTimer *parent = currentTimer_;
36 currentTimer_ = timer;
37 PandaRuntimeCallerStat *callerStat = &callerStat_[callerId];
38 timer->Start(callerStat, parent);
39 }
40
StopCount(const PandaRuntimeTimer *nowTimer)41 void EcmaRuntimeStat::StopCount(const PandaRuntimeTimer *nowTimer)
42 {
43 if (nowTimer != currentTimer_) {
44 return;
45 }
46 PandaRuntimeTimer *parentTimer = currentTimer_->Stop();
47 currentTimer_ = parentTimer;
48 }
49
Print() const50 void EcmaRuntimeStat::Print() const
51 {
52 if (currentTimer_ != nullptr) {
53 currentTimer_->Snapshot();
54 }
55 PrintAllStats();
56 }
57
ResetAllCount()58 void EcmaRuntimeStat::ResetAllCount()
59 {
60 while (currentTimer_ != nullptr) {
61 StopCount(currentTimer_);
62 }
63 for (auto &runCallerStat : callerStat_) {
64 runCallerStat.Reset();
65 }
66 }
67
PrintAllStats() const68 void EcmaRuntimeStat::PrintAllStats() const
69 {
70 LOG_ECMA(INFO) << "panda runtime stat:";
71 static constexpr int nameRightAdjustment = 45;
72 static constexpr int numberRightAdjustment = 12;
73 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "InterPreter && GC && C++ Builtin Function"
74 << std::setw(numberRightAdjustment) << "Time(ns)" << std::setw(numberRightAdjustment) << "Count"
75 << std::setw(numberRightAdjustment) << "MaxTime(ns)"
76 << std::setw(numberRightAdjustment) << "AvgTime(ns)";
77 LOG_ECMA(INFO) << "============================================================"
78 << "=========================================================";
79
80 CVector<PandaRuntimeCallerStat> callerStat;
81 for (auto &runCallerStat : callerStat_) {
82 callerStat.push_back(runCallerStat);
83 }
84 // Sort by TotalTime
85 std::sort(callerStat.begin(), callerStat.end(),
86 [](const PandaRuntimeCallerStat &a, const PandaRuntimeCallerStat &b) -> bool {
87 return a.TotalTime() > b.TotalTime();
88 });
89
90 uint64_t totalTime = 0;
91 uint64_t interpreterTotalTime = 0;
92 uint64_t builtinTotalTime = 0;
93 uint64_t abstractOperationTotalTime = 0;
94 uint64_t memoryTotalTime = 0;
95 uint64_t runtimeTotalTime = 0;
96 for (auto &runCallerStat : callerStat) {
97 if (runCallerStat.TotalCount() != 0) {
98 totalTime += runCallerStat.TotalTime();
99 CString header = runCallerStat.GetHeaderOfName();
100 if (header == CString("Interpreter")) {
101 interpreterTotalTime += runCallerStat.TotalTime();
102 } else if (header == CString("BuiltinsApi")) {
103 builtinTotalTime += runCallerStat.TotalTime();
104 } else if (header == CString("AbstractOperation")) {
105 abstractOperationTotalTime += runCallerStat.TotalTime();
106 } else if (header == CString("Memory")) {
107 memoryTotalTime += runCallerStat.TotalTime();
108 } else if (header == CString("Runtime")) {
109 runtimeTotalTime += runCallerStat.TotalTime();
110 }
111 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << runCallerStat.Name()
112 << std::setw(numberRightAdjustment) << runCallerStat.TotalTime()
113 << std::setw(numberRightAdjustment) << runCallerStat.TotalCount()
114 << std::setw(numberRightAdjustment) << runCallerStat.MaxTime()
115 << std::setw(numberRightAdjustment)
116 << runCallerStat.TotalTime() / runCallerStat.TotalCount();
117 }
118 }
119 LOG_ECMA(INFO) << "------------------------------------------------------------"
120 << "---------------------------------------------------------";
121 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Interpreter Total Time(ns)"
122 << std::setw(numberRightAdjustment) << interpreterTotalTime;
123 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "BuiltinsApi Total Time(ns)"
124 << std::setw(numberRightAdjustment) << builtinTotalTime;
125 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "AbstractOperation Total Time(ns)"
126 << std::setw(numberRightAdjustment) << abstractOperationTotalTime;
127 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Memory Total Time(ns)"
128 << std::setw(numberRightAdjustment) << memoryTotalTime;
129 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Runtime Total Time(ns)"
130 << std::setw(numberRightAdjustment) << runtimeTotalTime;
131 LOG_ECMA(INFO) << "------------------------------------------------------------"
132 << "---------------------------------------------------------";
133 LOG_ECMA(INFO) << std::right << std::setw(nameRightAdjustment) << "Total Time(ns)"
134 << std::setw(numberRightAdjustment) << totalTime;
135 }
136
EcmaRuntimeStatScope(EcmaVM *vm)137 EcmaRuntimeStatScope::EcmaRuntimeStatScope(EcmaVM *vm) : vm_(vm)
138 {
139 if (vm_->GetJSOptions().IsEnableRuntimeStat()) {
140 vm_->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(true);
141 }
142 }
143
~EcmaRuntimeStatScope()144 EcmaRuntimeStatScope::~EcmaRuntimeStatScope()
145 {
146 if (vm_->GetJSOptions().IsEnableRuntimeStat()) {
147 vm_->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(false);
148 }
149 vm_ = nullptr;
150 }
151 } // namespace panda::ecmascript
152