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 <chrono>
17 #include <cstdint>
18 #include <ctime>
19 #include <iomanip>
20 #include <iostream>
21 #include <map>
22 #include <string>
23
24 #include "transaction/rs_transaction_metric_collector.h"
25 #include "hilog/log.h"
26 #include "platform/common/rs_log.h"
27 #include "platform/common/rs_system_properties.h"
28
29 namespace OHOS {
30 namespace Rosen {
31 namespace {
32 const uint64_t PRECISION = 2;
33
34 const uint64_t COLLECT_INTERVAL = 5000;
35
36 const uint64_t MS_UNIT = 1000;
37
NowInMs()38 uint64_t NowInMs()
39 {
40 auto now = std::chrono::system_clock::now();
41 auto nowCastMs = std::chrono::time_point_cast<std::chrono::milliseconds>(now);
42 uint64_t msNow = (uint64_t) (nowCastMs.time_since_epoch().count());
43 return msNow;
44 }
45
MsToString(uint64_t ms)46 std::string MsToString(uint64_t ms)
47 {
48 std::chrono::duration<uint64_t, std::milli> dur(ms);
49 auto tp = std::chrono::system_clock::time_point(
50 std::chrono::duration_cast<std::chrono::system_clock::duration>(dur));
51 std::time_t t = std::chrono::system_clock::to_time_t(tp);
52 std::stringstream ss;
53 ss << std::put_time(std::localtime(&t), "%Y-%m-%d %H.%M.%S") << "." << ms % MS_UNIT;
54 return ss.str();
55 }
56 }
57
RSTransactionMetricPid()58 RSTransactionMetricPid::RSTransactionMetricPid() : prevTxTimestamp_(0)
59 {
60 }
61
Initiate(uint64_t rsTxSize,uint64_t currentTimestamp)62 void RSTransactionMetricPid::Initiate(uint64_t rsTxSize, uint64_t currentTimestamp)
63 {
64 prevTxTimestamp_ = currentTimestamp;
65 rsTxCount_ = 1;
66 rsTxIntervalSum_ = 0;
67 minRsTxInterval_ = std::numeric_limits<uint64_t>::max();
68 maxRsTxInterval_ = std::numeric_limits<uint64_t>::min();
69 rsTxSizeSum_ = rsTxSize;
70 minRsTxSize_ = rsTxSize;
71 maxRsTxSize_ = rsTxSize;
72 }
73
Update(uint64_t rsTxSize,uint64_t currentTimestamp)74 void RSTransactionMetricPid::Update(uint64_t rsTxSize, uint64_t currentTimestamp)
75 {
76 if (prevTxTimestamp_ == 0) {
77 Initiate(rsTxSize, currentTimestamp);
78 return;
79 }
80 uint64_t currentInterval = currentTimestamp - prevTxTimestamp_;
81 rsTxCount_++;
82 rsTxIntervalSum_ += currentInterval;
83 minRsTxInterval_ = minRsTxInterval_ < currentInterval ? minRsTxInterval_ : currentInterval;
84 maxRsTxInterval_ = maxRsTxInterval_ < currentInterval ? currentInterval : maxRsTxInterval_;
85
86 rsTxSizeSum_ += rsTxSize;
87 minRsTxSize_ = minRsTxSize_ < rsTxSize ? minRsTxSize_ : rsTxSize;
88 maxRsTxSize_ = maxRsTxSize_ < rsTxSize ? rsTxSize : maxRsTxSize_;
89 prevTxTimestamp_ = currentTimestamp;
90 }
91
ToString() const92 std::string RSTransactionMetricPid::ToString() const
93 {
94 double avgCmd = 0;
95 if (rsTxCount_ > 0) {
96 avgCmd = static_cast<double>(rsTxSizeSum_) / static_cast<double>(rsTxCount_);
97 }
98 uint64_t minRsTxInterval = 0;
99 uint64_t maxRsTxInterval = 0;
100 if (rsTxCount_ > 1) {
101 minRsTxInterval = minRsTxInterval_;
102 maxRsTxInterval = maxRsTxInterval_;
103 }
104
105 std::stringstream stream;
106 stream << "count:" << rsTxCount_ << ", ";
107 stream << "minInterval:" << minRsTxInterval << ", ";
108 stream << "maxInterval:" << maxRsTxInterval << ", ";
109 stream << "minCmd:" << minRsTxSize_ << ", ";
110 stream << "maxCmd:" << maxRsTxSize_ << ", ";
111 stream << "totalCmd:" << rsTxSizeSum_ << ", ";
112 stream << "avgCmd:" << std::fixed << std::setprecision(PRECISION) << avgCmd;
113 return stream.str();
114 }
115
GetInstance()116 RSTransactionMetricCollector &RSTransactionMetricCollector::GetInstance()
117 {
118 static RSTransactionMetricCollector instance;
119 return instance;
120 }
121
RSTransactionMetricCollector()122 RSTransactionMetricCollector::RSTransactionMetricCollector() : collectStartTimestamp_(0)
123 {
124 }
125
Reset(uint64_t ms)126 void RSTransactionMetricCollector::Reset(uint64_t ms)
127 {
128 collectStartTimestamp_ = ms;
129 collectEndTimestamp_ = ms;
130 pidMetrics_.clear();
131 }
132
Collect(std::unique_ptr<RSTransactionData> & rsTransactionData)133 void RSTransactionMetricCollector::Collect(std::unique_ptr<RSTransactionData> &rsTransactionData)
134 {
135 if (!RSSystemProperties::IsBetaRelease()) {
136 return;
137 }
138 uint64_t currentTimestamp = NowInMs();
139 if (collectStartTimestamp_ == 0) {
140 Reset(currentTimestamp);
141 }
142
143 uint64_t sinceStart = currentTimestamp - collectStartTimestamp_;
144 pid_t sendingPid = rsTransactionData->GetSendingPid();
145 uint64_t rsTxSize = rsTransactionData->GetCommandCount();
146 pid_t fakePidAsAll = -1;
147 for (const pid_t &pid: {fakePidAsAll, sendingPid}) {
148 pidMetrics_[pid].Update(rsTxSize, currentTimestamp);
149 }
150
151 if (sinceStart > COLLECT_INTERVAL) {
152 collectEndTimestamp_ = currentTimestamp;
153 Log();
154 Reset(currentTimestamp);
155 return;
156 }
157 }
158
Log()159 void RSTransactionMetricCollector::Log()
160 {
161 std::string collectStartTimestamp = MsToString(collectStartTimestamp_);
162 std::string collectEndTimestamp = MsToString(collectEndTimestamp_);
163
164 std::map<pid_t, RSTransactionMetricPid> ordered(pidMetrics_.begin(), pidMetrics_.end());
165 for (auto it = ordered.begin(); it != ordered.end(); ++it) {
166 RS_LOGI("[%{public}s - %{public}s], %{public}d %{public}s",
167 collectStartTimestamp.c_str(), collectEndTimestamp.c_str(),
168 (std::int32_t)(it->first), it->second.ToString().c_str());
169 }
170 }
171
172 } // namespace Rosen
173 } // namespace OHOS