1 /*
2 * Copyright (c) 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 "base/log/ace_performance_monitor.h"
17
18 #include <sstream>
19
20 #include "base/json/json_util.h"
21 #include "base/log/ace_trace.h"
22 #include "core/common/container.h"
23 #include "core/pipeline_ng/pipeline_context.h"
24
25 namespace OHOS::Ace {
26 using namespace std;
27 using namespace std::chrono;
28 namespace {
GetTimePoint(TimePoint & now)29 void GetTimePoint(TimePoint& now)
30 {
31 if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
32 now = steady_clock::now();
33 }
34 }
35 } // namespace
36
ScopedMonitor(MonitorTag tag,int32_t instanceId)37 ScopedMonitor::ScopedMonitor(MonitorTag tag, int32_t instanceId) : tag_(tag), instanceId_(instanceId)
38 {
39 if (instanceId == -1) {
40 return;
41 }
42 GetTimePoint(begin_);
43 ArkUIPerfMonitor::GetPerfMonitor(instanceId)->SetRecordingStatus(tag_, MonitorStatus::RUNNING);
44 }
45
~ScopedMonitor()46 ScopedMonitor::~ScopedMonitor()
47 {
48 if (instanceId_ == -1) {
49 return;
50 }
51 GetTimePoint(end_);
52 ArkUIPerfMonitor::GetPerfMonitor(instanceId_)->RecordTimeSlice(
53 tag_, duration_cast<nanoseconds>(end_ - begin_).count());
54 }
55
GetPerfMonitor(int32_t instanceId)56 std::shared_ptr<ArkUIPerfMonitor> ArkUIPerfMonitor::GetPerfMonitor(int32_t instanceId)
57 {
58 auto container = Container::GetContainer(instanceId);
59 if (!container) {
60 return std::make_shared<ArkUIPerfMonitor>();
61 }
62 auto pipeline = container->GetPipelineContext();
63 if (!pipeline) {
64 return std::make_shared<ArkUIPerfMonitor>();
65 }
66 return pipeline->GetPerfMonitor();
67 }
68
ArkUIPerfMonitor()69 ArkUIPerfMonitor::ArkUIPerfMonitor()
70 {
71 InitPerfMonitor();
72 }
73
StartPerf()74 void ArkUIPerfMonitor::StartPerf()
75 {
76 GetTimePoint(begin_);
77 ClearPerfMonitor();
78 }
79
FinishPerf()80 void ArkUIPerfMonitor::FinishPerf()
81 {
82 GetTimePoint(end_);
83 FlushPerfMonitor();
84 ClearPerfMonitor();
85 }
86
RecordTimeSlice(MonitorTag tag,int64_t duration)87 void ArkUIPerfMonitor::RecordTimeSlice(MonitorTag tag, int64_t duration)
88 {
89 SetRecordingStatus(tag, MonitorStatus::IDLE);
90 if (tag == MonitorTag::STATIC_API) {
91 propertyNum_++;
92 if (!monitorStatus_) {
93 return;
94 }
95 timeSlice_[tag] += duration;
96 return;
97 }
98 if (monitorStatus_ == 0) {
99 timeSlice_[tag] += duration;
100 }
101 }
102
RecordStateMgmtNode(int64_t num)103 void ArkUIPerfMonitor::RecordStateMgmtNode(int64_t num)
104 {
105 stateMgmtNodeNum_ += num;
106 }
107
RecordLayoutNode(int64_t num)108 void ArkUIPerfMonitor::RecordLayoutNode(int64_t num)
109 {
110 layoutNodeNum_ += num;
111 }
112
RecordRenderNode(int64_t num)113 void ArkUIPerfMonitor::RecordRenderNode(int64_t num)
114 {
115 renderNodeNum_ += num;
116 }
117
RecordDisplaySyncRate(int32_t displaySyncRate)118 void ArkUIPerfMonitor::RecordDisplaySyncRate(int32_t displaySyncRate)
119 {
120 displaySyncRate_ = displaySyncRate;
121 }
122
SetRecordingStatus(MonitorTag tag,MonitorStatus status)123 void ArkUIPerfMonitor::SetRecordingStatus(MonitorTag tag, MonitorStatus status)
124 {
125 if (tag == MonitorTag::STATIC_API) {
126 return;
127 }
128 switch (status) {
129 case MonitorStatus::RUNNING:
130 ++monitorStatus_;
131 break;
132 case MonitorStatus::IDLE:
133 --monitorStatus_;
134 break;
135 }
136 }
137
InitPerfMonitor()138 void ArkUIPerfMonitor::InitPerfMonitor()
139 {
140 monitorStatus_ = 0;
141 ClearPerfMonitor();
142 }
143
ClearPerfMonitor()144 void ArkUIPerfMonitor::ClearPerfMonitor()
145 {
146 timeSlice_[MonitorTag::COMPONENT_CREATION] = 0;
147 timeSlice_[MonitorTag::COMPONENT_LIFECYCLE] = 0;
148 timeSlice_[MonitorTag::COMPONENT_UPDATE] = 0;
149 timeSlice_[MonitorTag::JS_CALLBACK] = 0;
150 timeSlice_[MonitorTag::STATIC_API] = 0;
151 timeSlice_[MonitorTag::OTHER] = 0;
152 propertyNum_ = 0;
153 stateMgmtNodeNum_ = 0;
154 layoutNodeNum_ = 0;
155 renderNodeNum_ = 0;
156 displaySyncRate_ = 0;
157 }
158
FlushPerfMonitor()159 void ArkUIPerfMonitor::FlushPerfMonitor()
160 {
161 auto total = static_cast<int64_t>(duration_cast<nanoseconds>(end_ - begin_).count());
162 auto frameWork = total - timeSlice_[MonitorTag::COMPONENT_CREATION] - timeSlice_[MonitorTag::COMPONENT_LIFECYCLE] -
163 timeSlice_[MonitorTag::COMPONENT_UPDATE] - timeSlice_[MonitorTag::JS_CALLBACK] +
164 timeSlice_[MonitorTag::STATIC_API] - timeSlice_[MonitorTag::OTHER];
165 #if ORIGIN_PERF_MONITOR
166 auto json = JsonUtil::Create(true);
167 json->Put("state_mgmt", stateMgmtNodeNum_);
168 json->Put("layout", layoutNodeNum_);
169 json->Put("render", renderNodeNum_);
170 json->Put("property", propertyNum_);
171 json->Put("total", total);
172 json->Put("framework", frameWork);
173 json->Put("display_sync_rate", displaySyncRate_);
174 ACE_SCOPED_TRACE("ArkUIPerfMonitor %s", json->ToString().c_str());
175 #else
176 std::ostringstream oss;
177 oss << "{\'state_mgmt\':" << stateMgmtNodeNum_;
178 oss << ",\'layout\':" << layoutNodeNum_;
179 oss << ",\'render\':" << renderNodeNum_;
180 oss << ",\'property\':" << propertyNum_;
181 oss << ",\'total\':" << total;
182 oss << ",\'framework\':" << frameWork;
183 oss << ",\'display_sync_rate\':" << displaySyncRate_;
184 oss << "}";
185 ACE_SCOPED_TRACE("ArkUIPerfMonitor %s", oss.str().c_str());
186 #endif
187 }
188 } // namespace OHOS::Ace
189