• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "platform/ohos/rs_node_stats.h"
17 
18 #include <algorithm>
19 #include <chrono>
20 #include <sys/time.h>
21 #include <unistd.h>
22 
23 #include "hisysevent.h"
24 #include "rs_trace.h"
25 
26 #include "common/rs_background_thread.h"
27 #include "platform/common/rs_log.h"
28 #include "platform/common/rs_system_properties.h"
29 #include "platform/common/rs_hisysevent.h"
30 
31 namespace OHOS {
32 namespace Rosen {
33 namespace {
34 constexpr size_t TOP1_INDEX = 0;
35 constexpr size_t TOP2_INDEX = 1;
36 constexpr size_t TOP3_INDEX = 2;
37 constexpr size_t EMPTY_NODE_DESCRIPTION_SIZE = 0;
38 constexpr RSNodeCount NONE_NODE_COUNT = 0;
39 const RSNodeDescription NONE_NODE_DESCRIPTION = "NaN";
40 const RSNodeDescription EMPTY_NODE_DESCRIPTION = "EmptyName";
41 }
42 
GetInstance()43 RSNodeStats& RSNodeStats::GetInstance()
44 {
45     static RSNodeStats instance;
46     return instance;
47 }
48 
AddNodeStats(const RSNodeStatsType & nodeStats,RSNodeStatsUpdateMode updateMode)49 void RSNodeStats::AddNodeStats(const RSNodeStatsType& nodeStats, RSNodeStatsUpdateMode updateMode)
50 {
51     std::lock_guard<std::mutex> lock(mutex_);
52     NodeId nodeId = std::get<NodeId>(nodeStats);
53     if (updateMode == RSNodeStatsUpdateMode::DISCARD_DUPLICATE && rsNodeIdSet_.find(nodeId) != rsNodeIdSet_.end()) {
54         return;
55     }
56     rsNodeIdSet_.insert(nodeId);
57     rsNodeStatsVec_.push_back(nodeStats);
58     rsNodeCountTotal_ += std::get<RSNodeCount>(nodeStats);
59 }
60 
ClearNodeStats()61 void RSNodeStats::ClearNodeStats()
62 {
63     std::lock_guard<std::mutex> lock(mutex_);
64     rsNodeIdSet_.clear();
65     rsNodeStatsVec_.clear();
66     rsNodeCountTotal_ = 0;
67 }
68 
ReportRSNodeLimitExceeded()69 void RSNodeStats::ReportRSNodeLimitExceeded()
70 {
71     std::lock_guard<std::mutex> lock(mutex_);
72     uint32_t rsNodeCountTotal = rsNodeCountTotal_;
73     uint32_t rsNodeLimit = 0;
74     uint32_t rsNodeReportLimit = 0;
75     GetCurrentRSNodeLimit(rsNodeLimit, rsNodeReportLimit);
76     if (rsNodeCountTotal < rsNodeReportLimit) {
77         return;
78     }
79     int64_t curSysTime = GetCurrentSystimeMs();
80     int64_t curSteadyTime = GetCurrentSteadyTimeMs();
81     if (lastReportTime_ != TIMESTAMP_INITIAL && lastReportTimeSteady_ != TIMESTAMP_INITIAL &&
82         (curSysTime - lastReportTime_ <= REPORT_INTERVAL_LIMIT ||
83         curSteadyTime - lastReportTimeSteady_ <= REPORT_INTERVAL_LIMIT)) {
84         return;
85     }
86     SortNodeStats();
87     const auto nodeInfoTop1 = GetNodeStatsToReportByIndex(TOP1_INDEX);
88     const auto nodeInfoTop2 = GetNodeStatsToReportByIndex(TOP2_INDEX);
89     const auto nodeInfoTop3 = GetNodeStatsToReportByIndex(TOP3_INDEX);
90     uint32_t appWindowTotal = static_cast<uint32_t>(rsNodeStatsVec_.size());
91     RS_TRACE_NAME_FMT("RSNodeStats::ReportRSNodeLimitExceeded "
92                       "nodeCount=%u, top1=%u [%s], top2=%u [%s], top3=%u [%s], timestamp=%" PRId64,
93                       rsNodeCountTotal, nodeInfoTop1.second, nodeInfoTop1.first.c_str(), nodeInfoTop2.second,
94                       nodeInfoTop2.first.c_str(), nodeInfoTop3.second, nodeInfoTop3.first.c_str(), curSysTime);
95     RSBackgroundThread::Instance().PostTask([
96         rsNodeLimit, rsNodeCountTotal, curSysTime, appWindowTotal, nodeInfoTop1, nodeInfoTop2, nodeInfoTop3]() {
97         RS_TRACE_NAME("RSNodeStats::ReportRSNodeLimitExceeded in RSBackgroundThread");
98         RSHiSysEvent::EventWrite(RSEventName::RS_NODE_LIMIT_EXCEEDED, RSEventType::RS_BEHAVIOR,
99             "RS_NODE_LIMIT", rsNodeLimit,
100             "RS_ACTUAL_NODE", rsNodeCountTotal,
101             "TIMESTAMP", static_cast<uint64_t>(curSysTime),
102             "RS_APP_WINDOW_TOTAL", appWindowTotal,
103             "RS_TOP1_APP_NAME", nodeInfoTop1.first,
104             "RS_TOP1_APP_NODE", nodeInfoTop1.second,
105             "RS_TOP2_APP_NAME", nodeInfoTop2.first,
106             "RS_TOP2_APP_NODE", nodeInfoTop2.second,
107             "RS_TOP3_APP_NAME", nodeInfoTop3.first,
108             "RS_TOP3_APP_NODE", nodeInfoTop3.second);
109     });
110     lastReportTime_ = curSysTime;
111     lastReportTimeSteady_ = curSteadyTime;
112 }
113 
SortNodeStats(bool isSortByNodeCountDescendingOrder)114 void RSNodeStats::SortNodeStats(bool isSortByNodeCountDescendingOrder)
115 {
116     std::sort(rsNodeStatsVec_.begin(), rsNodeStatsVec_.end());
117     if (isSortByNodeCountDescendingOrder) {
118         std::reverse(rsNodeStatsVec_.begin(), rsNodeStatsVec_.end());
119     }
120 }
121 
GetNodeStatsToReportByIndex(size_t index) const122 std::pair<RSNodeDescription, RSNodeCount> RSNodeStats::GetNodeStatsToReportByIndex(size_t index) const
123 {
124     if (index < rsNodeStatsVec_.size()) {
125         const RSNodeStatsType& nodeStats = rsNodeStatsVec_.at(index);
126         RSNodeDescription nodeDescription = std::get<RSNodeDescription>(nodeStats);
127         nodeDescription = CheckEmptyAndReviseNodeDescription(nodeDescription);
128         RSNodeCount nodeCount = std::get<RSNodeCount>(nodeStats);
129         return std::make_pair(nodeDescription, nodeCount);
130     }
131     return std::make_pair(NONE_NODE_DESCRIPTION, NONE_NODE_COUNT);
132 }
133 
CheckEmptyAndReviseNodeDescription(const RSNodeDescription & nodeDescription) const134 RSNodeDescription RSNodeStats::CheckEmptyAndReviseNodeDescription(const RSNodeDescription& nodeDescription) const
135 {
136     if (nodeDescription.size() == EMPTY_NODE_DESCRIPTION_SIZE) {
137         return EMPTY_NODE_DESCRIPTION;
138     }
139     return nodeDescription;
140 }
141 
GetCurrentRSNodeLimit(uint32_t & rsNodeLimit,uint32_t & rsNodeReportLimit) const142 void RSNodeStats::GetCurrentRSNodeLimit(uint32_t& rsNodeLimit, uint32_t& rsNodeReportLimit) const
143 {
144     int rsNodeLimitProperty = std::clamp(
145         RSSystemProperties::GetRSNodeLimit(), RS_NODE_LIMIT_PROPERTY_MIN, RS_NODE_LIMIT_PROPERTY_MAX);
146     rsNodeLimit = static_cast<uint32_t>(rsNodeLimitProperty);
147     rsNodeReportLimit = static_cast<uint32_t>(rsNodeLimitProperty * RS_NODE_LIMIT_REPORT_RATIO);
148 }
149 
GetCurrentSystimeMs() const150 int64_t RSNodeStats::GetCurrentSystimeMs() const
151 {
152     auto curTime = std::chrono::system_clock::now().time_since_epoch();
153     int64_t curSysTime = std::chrono::duration_cast<std::chrono::milliseconds>(curTime).count();
154     return curSysTime;
155 }
156 
GetCurrentSteadyTimeMs() const157 int64_t RSNodeStats::GetCurrentSteadyTimeMs() const
158 {
159     auto curTime = std::chrono::steady_clock::now().time_since_epoch();
160     int64_t curSteadyTime = std::chrono::duration_cast<std::chrono::milliseconds>(curTime).count();
161     return curSteadyTime;
162 }
163 
164 } // namespace Rosen
165 } // namespace OHOS
166