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 "base/json/json_util.h"
19 #include "base/log/ace_trace.h"
20 
21 namespace OHOS::Ace {
22 using namespace std;
23 using namespace std::chrono;
24 namespace {
GetTimePoint(TimePoint & now)25 void GetTimePoint(TimePoint& now)
26 {
27     if (SystemProperties::GetAcePerformanceMonitorEnabled()) {
28         now = steady_clock::now();
29     }
30 }
31 } // namespace
32 
ScopedMonitor(MonitorTag tag)33 ScopedMonitor::ScopedMonitor(MonitorTag tag) : tag_(tag)
34 {
35     GetTimePoint(begin_);
36     ArkUIPerfMonitor::GetInstance().SetRecordingStatus(tag_, MonitorStatus::RUNNING);
37 }
38 
~ScopedMonitor()39 ScopedMonitor::~ScopedMonitor()
40 {
41     GetTimePoint(end_);
42     ArkUIPerfMonitor::GetInstance().RecordTimeSlice(tag_, duration_cast<nanoseconds>(end_ - begin_).count());
43 }
44 
GetInstance()45 ArkUIPerfMonitor& ArkUIPerfMonitor::GetInstance()
46 {
47     static ArkUIPerfMonitor instance;
48     return instance;
49 }
50 
ArkUIPerfMonitor()51 ArkUIPerfMonitor::ArkUIPerfMonitor()
52 {
53     InitPerfMonitor();
54 }
55 
StartPerf()56 void ArkUIPerfMonitor::StartPerf()
57 {
58     GetTimePoint(begin_);
59     ClearPerfMonitor();
60 }
61 
FinishPerf()62 void ArkUIPerfMonitor::FinishPerf()
63 {
64     GetTimePoint(end_);
65     FlushPerfMonitor();
66     ClearPerfMonitor();
67 }
68 
RecordTimeSlice(MonitorTag tag,int64_t duration)69 void ArkUIPerfMonitor::RecordTimeSlice(MonitorTag tag, int64_t duration)
70 {
71     SetRecordingStatus(tag, MonitorStatus::IDLE);
72     if (tag == MonitorTag::STATIC_API) {
73         propertyNum_++;
74         if (!monitorStatus_) {
75             return;
76         }
77         timeSlice_[tag] += duration;
78         return;
79     }
80     if (monitorStatus_ == 0) {
81         timeSlice_[tag] += duration;
82     }
83 }
84 
RecordStateMgmtNode(int64_t num)85 void ArkUIPerfMonitor::RecordStateMgmtNode(int64_t num)
86 {
87     stateMgmtNodeNum_ += num;
88 }
89 
RecordLayoutNode(int64_t num)90 void ArkUIPerfMonitor::RecordLayoutNode(int64_t num)
91 {
92     layoutNodeNum_ += num;
93 }
94 
RecordRenderNode(int64_t num)95 void ArkUIPerfMonitor::RecordRenderNode(int64_t num)
96 {
97     renderNodeNum_ += num;
98 }
99 
RecordDisplaySyncRate(int32_t displaySyncRate)100 void ArkUIPerfMonitor::RecordDisplaySyncRate(int32_t displaySyncRate)
101 {
102     displaySyncRate_ = displaySyncRate;
103 }
104 
SetRecordingStatus(MonitorTag tag,MonitorStatus status)105 void ArkUIPerfMonitor::SetRecordingStatus(MonitorTag tag, MonitorStatus status)
106 {
107     if (tag == MonitorTag::STATIC_API) {
108         return;
109     }
110     switch (status) {
111         case MonitorStatus::RUNNING:
112             ++monitorStatus_;
113             break;
114         case MonitorStatus::IDLE:
115             --monitorStatus_;
116             break;
117     }
118 }
119 
InitPerfMonitor()120 void ArkUIPerfMonitor::InitPerfMonitor()
121 {
122     monitorStatus_ = 0;
123     ClearPerfMonitor();
124 }
125 
ClearPerfMonitor()126 void ArkUIPerfMonitor::ClearPerfMonitor()
127 {
128     timeSlice_[MonitorTag::COMPONENT_CREATION] = 0;
129     timeSlice_[MonitorTag::COMPONENT_LIFECYCLE] = 0;
130     timeSlice_[MonitorTag::COMPONENT_UPDATE] = 0;
131     timeSlice_[MonitorTag::JS_CALLBACK] = 0;
132     timeSlice_[MonitorTag::STATIC_API] = 0;
133     timeSlice_[MonitorTag::OTHER] = 0;
134     propertyNum_ = 0;
135     stateMgmtNodeNum_ = 0;
136     layoutNodeNum_ = 0;
137     renderNodeNum_ = 0;
138     displaySyncRate_ = 0;
139 }
140 
FlushPerfMonitor()141 void ArkUIPerfMonitor::FlushPerfMonitor()
142 {
143     auto total = static_cast<int64_t>(duration_cast<nanoseconds>(end_ - begin_).count());
144     auto frameWork = total - timeSlice_[MonitorTag::COMPONENT_CREATION] - timeSlice_[MonitorTag::COMPONENT_LIFECYCLE] -
145                      timeSlice_[MonitorTag::COMPONENT_UPDATE] - timeSlice_[MonitorTag::JS_CALLBACK] +
146                      timeSlice_[MonitorTag::STATIC_API] - timeSlice_[MonitorTag::OTHER];
147     auto json = JsonUtil::Create(true);
148     json->Put("state_mgmt", stateMgmtNodeNum_);
149     json->Put("layout", layoutNodeNum_);
150     json->Put("render", renderNodeNum_);
151     json->Put("property", propertyNum_);
152     json->Put("total", total);
153     json->Put("framework", frameWork);
154     json->Put("display_sync_rate", displaySyncRate_);
155     ACE_SCOPED_TRACE("ArkUIPerfMonitor %s", json->ToString().c_str());
156 }
157 } // namespace OHOS::Ace
158