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