• 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 <string>
17 #include <sstream>
18 #include "include/sp_log.h"
19 #include "include/sp_utils.h"
20 #include "include/GpuCounter.h"
21 #include "include/GpuCounterCallback.h"
22 
23 namespace OHOS {
24     namespace SmartPerf {
GpuCounterCallbackImpl()25         GpuCounterCallbackImpl::GpuCounterCallbackImpl()
26         {
27             GpuPerfInfo firstData;
28             firstData.startTime = SPUtils::GetCurTime();
29             firstData.duration = 0;
30             firstData.gpuActive = 0;
31             firstData.drawCalls = 0;
32             firstData.primitives = 0;
33             firstData.vertexCounts = 0;
34             firstData.totalInstruments = 0;
35             firstData.gpuLoadPercentage = 0;
36             firstData.vertexLoadPercentage = 0;
37             firstData.fragmentLoadPercentage = 0;
38             firstData.computeLoadPercentage = 0;
39             firstData.textureLoadPercentage = 0;
40             firstData.memoryReadBandwidth = 0;
41             firstData.memoryWriteBandwidth = 0;
42             firstData.memoryBandwidthPercentage = 0;
43             firstData.remainTime = maxTime;
44             realtimeGpuPerfInfoData = firstData;
45             gpuCounter.push_back(firstData);
46         }
47 
48 
JoinSocketDataPercentFunction(uint32_t itemFirst,int32_t durationFirst,uint32_t itemSecond,int32_t durationSecond) const49         unsigned long long GpuCounterCallbackImpl::JoinSocketDataPercentFunction(uint32_t itemFirst,
50             int32_t durationFirst, uint32_t itemSecond, int32_t durationSecond) const
51         {
52             return (static_cast<unsigned long long>(itemFirst) * static_cast<unsigned long long>(durationFirst) +
53                 static_cast<unsigned long long>(itemSecond) * static_cast<unsigned long long>(durationSecond)) /
54                 (static_cast<unsigned long long>(durationFirst) + static_cast<unsigned long long>(durationSecond));
55         }
56 
JoinSocketDataValue(GpuPerfInfo * newData)57         void GpuCounterCallbackImpl::JoinSocketDataValue(GpuPerfInfo *newData)
58         {
59             realtimeGpuPerfInfoData.gpuActive += newData->gpuActive;
60             realtimeGpuPerfInfoData.drawCalls += newData->drawCalls;
61             realtimeGpuPerfInfoData.primitives += newData->primitives;
62             realtimeGpuPerfInfoData.vertexCounts += newData->vertexCounts;
63             realtimeGpuPerfInfoData.totalInstruments += newData->totalInstruments;
64             realtimeGpuPerfInfoData.memoryReadBandwidth += newData->memoryReadBandwidth;
65             realtimeGpuPerfInfoData.memoryWriteBandwidth += newData->memoryWriteBandwidth;
66         }
67 
JoinSocketDataPercent(GpuPerfInfo * newData)68         void GpuCounterCallbackImpl::JoinSocketDataPercent(GpuPerfInfo *newData)
69         {
70             realtimeGpuPerfInfoData.gpuLoadPercentage = JoinSocketDataPercentFunction(
71                 realtimeGpuPerfInfoData.gpuLoadPercentage, realtimeGpuPerfInfoData.duration,
72                 newData->gpuLoadPercentage, newData->duration);
73             realtimeGpuPerfInfoData.vertexLoadPercentage = JoinSocketDataPercentFunction(
74                 realtimeGpuPerfInfoData.vertexLoadPercentage, realtimeGpuPerfInfoData.duration,
75                 newData->vertexLoadPercentage, newData->duration);
76             realtimeGpuPerfInfoData.fragmentLoadPercentage = JoinSocketDataPercentFunction(
77                 realtimeGpuPerfInfoData.fragmentLoadPercentage, realtimeGpuPerfInfoData.duration,
78                 newData->fragmentLoadPercentage, newData->duration);
79             realtimeGpuPerfInfoData.computeLoadPercentage = JoinSocketDataPercentFunction(
80                 realtimeGpuPerfInfoData.computeLoadPercentage, realtimeGpuPerfInfoData.duration,
81                 newData->computeLoadPercentage, newData->duration);
82             realtimeGpuPerfInfoData.textureLoadPercentage = JoinSocketDataPercentFunction(
83                 realtimeGpuPerfInfoData.textureLoadPercentage, realtimeGpuPerfInfoData.duration,
84                 newData->textureLoadPercentage, newData->duration);
85         }
86 
JoinSocketData(GpuPerfInfo * newData)87         void GpuCounterCallbackImpl::JoinSocketData(GpuPerfInfo *newData)
88         {
89             JoinSocketDataValue(newData);
90             JoinSocketDataPercent(newData);
91 
92             realtimeGpuPerfInfoData.duration += newData->duration;
93         }
94 
SplitSocketDataValueFunction(uint32_t value,int32_t interval,int32_t duration) const95         unsigned long long GpuCounterCallbackImpl::SplitSocketDataValueFunction(uint32_t value, int32_t interval,
96             int32_t duration) const
97         {
98             return static_cast<unsigned long long>(value) *
99                 static_cast<unsigned long long>(interval) /
100                 static_cast<unsigned long long>(duration);
101         }
102 
SplitSocketDataValue(int32_t interval)103         void GpuCounterCallbackImpl::SplitSocketDataValue(int32_t interval)
104         {
105             GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
106 
107             unsigned long long gpuActiveTargetValue = SplitSocketDataValueFunction(
108                 realtimeGpuPerfInfoData.gpuActive, interval,
109                 realtimeGpuPerfInfoData.duration);
110             unsigned long long drawCallsTargetValue = SplitSocketDataValueFunction(
111                 realtimeGpuPerfInfoData.drawCalls, interval,
112                 realtimeGpuPerfInfoData.duration);
113             unsigned long long primitivesTargetValue = SplitSocketDataValueFunction(
114                 realtimeGpuPerfInfoData.primitives, interval,
115                 realtimeGpuPerfInfoData.duration);
116             unsigned long long vertexCountsTargetValue = SplitSocketDataValueFunction(
117                 realtimeGpuPerfInfoData.vertexCounts, interval,
118                 realtimeGpuPerfInfoData.duration);
119             unsigned long long totalInstrumentsTargetValue = SplitSocketDataValueFunction(
120                 realtimeGpuPerfInfoData.totalInstruments, interval,
121                 realtimeGpuPerfInfoData.duration);
122             unsigned long long memoryReadBandwidthTargetValue = SplitSocketDataValueFunction(
123                 realtimeGpuPerfInfoData.memoryReadBandwidth, interval,
124                 realtimeGpuPerfInfoData.duration);
125             unsigned long long memoryWriteBandwidthTargetValue = SplitSocketDataValueFunction(
126                 realtimeGpuPerfInfoData.memoryWriteBandwidth, interval,
127                 realtimeGpuPerfInfoData.duration);
128 
129             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
130                 realtimeGpuPerfInfoData.gpuActive - gpuActiveTargetValue) + "_");
131             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
132                 realtimeGpuPerfInfoData.drawCalls - drawCallsTargetValue) + "_");
133             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
134                 realtimeGpuPerfInfoData.primitives - primitivesTargetValue) + "_");
135             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
136                 realtimeGpuPerfInfoData.vertexCounts - vertexCountsTargetValue) + "_");
137             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
138                 realtimeGpuPerfInfoData.totalInstruments - totalInstrumentsTargetValue) + "_");
139             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
140                 realtimeGpuPerfInfoData.memoryReadBandwidth - memoryReadBandwidthTargetValue) + "_");
141             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
142                 realtimeGpuPerfInfoData.memoryWriteBandwidth - memoryWriteBandwidthTargetValue) + "_");
143 
144             realtimeGpuPerfInfoData.gpuActive = gpuActiveTargetValue;
145             realtimeGpuPerfInfoData.drawCalls = drawCallsTargetValue;
146             realtimeGpuPerfInfoData.primitives = primitivesTargetValue;
147             realtimeGpuPerfInfoData.vertexCounts = vertexCountsTargetValue;
148             realtimeGpuPerfInfoData.totalInstruments = totalInstrumentsTargetValue;
149             realtimeGpuPerfInfoData.memoryReadBandwidth = memoryReadBandwidthTargetValue;
150             realtimeGpuPerfInfoData.memoryWriteBandwidth = memoryWriteBandwidthTargetValue;
151         }
152 
SplitSocketDataPercent()153         void GpuCounterCallbackImpl::SplitSocketDataPercent()
154         {
155             GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
156 
157             gpuCounterInstance.AddGpuCounterRealtimeData(
158                 std::to_string(realtimeGpuPerfInfoData.gpuLoadPercentage) + "_");
159             gpuCounterInstance.AddGpuCounterRealtimeData(
160                 std::to_string(realtimeGpuPerfInfoData.vertexLoadPercentage) + "_");
161             gpuCounterInstance.AddGpuCounterRealtimeData(
162                 std::to_string(realtimeGpuPerfInfoData.fragmentLoadPercentage) + "_");
163             gpuCounterInstance.AddGpuCounterRealtimeData(
164                 std::to_string(realtimeGpuPerfInfoData.computeLoadPercentage) + "_");
165             gpuCounterInstance.AddGpuCounterRealtimeData(
166                 std::to_string(realtimeGpuPerfInfoData.textureLoadPercentage) + ";");
167         }
168 
SplitSocketData()169         void GpuCounterCallbackImpl::SplitSocketData()
170         {
171             int32_t interval = realtimeGpuPerfInfoData.duration - maxDuration;
172             SplitSocketDataValue(interval);
173             SplitSocketDataPercent();
174             realtimeGpuPerfInfoData.duration = interval;
175         }
176 
GetRealTime(GpuPerfInfo * newData)177         void GpuCounterCallbackImpl::GetRealTime(GpuPerfInfo *newData)
178         {
179             if (newData == nullptr) {
180                 WLOGE("GetRealTime newData is nullptr");
181                 return;
182             }
183 
184             GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
185 
186             JoinSocketData(newData);
187             if ((realtimeGpuPerfInfoData.duration == 0) || (newData->duration == 0)) {
188                 WLOGE("Invalid duration found: realtime = %d, newData = %d",
189                     realtimeGpuPerfInfoData.duration, newData->duration);
190                 return;
191             }
192             gpuCounterInstance.GetRealtimeDataLock().lock();
193             while (realtimeGpuPerfInfoData.duration >= maxDuration) {
194                 SplitSocketData();
195             }
196             gpuCounterInstance.GetRealtimeDataLock().unlock();
197         }
198 
GetGpuPerfInfoItem(const GpuPerfInfo * itemData) const199         std::string GpuCounterCallbackImpl::GetGpuPerfInfoItem(const GpuPerfInfo *itemData) const
200         {
201             std::ostringstream oss;
202             if (itemData == nullptr) {
203                 WLOGE("GpuCounter get itemData is nullptr");
204                 return "";
205             }
206             oss << itemData->startTime << ","
207                 << itemData->duration << ","
208                 << itemData->gpuActive << ","
209                 << itemData->drawCalls << ","
210                 << itemData->primitives << ","
211                 << itemData->vertexCounts << ","
212                 << itemData->totalInstruments << ","
213                 << itemData->gpuLoadPercentage << ","
214                 << itemData->vertexLoadPercentage << ","
215                 << itemData->fragmentLoadPercentage << ","
216                 << itemData->computeLoadPercentage << ","
217                 << itemData->textureLoadPercentage << ","
218                 << itemData->memoryReadBandwidth << ","
219                 << itemData->memoryWriteBandwidth << ","
220                 << itemData->memoryBandwidthPercentage << ",";
221             return oss.str();
222         }
223 
OnGpuData(std::vector<GpuPerfInfo> & gpuPerfInfos)224         int GpuCounterCallbackImpl::OnGpuData(std::vector <GpuPerfInfo> &gpuPerfInfos)
225         {
226             if (gpuPerfInfos.empty()) {
227                 WLOGE("Receive gpuPerfInfos is empty!");
228                 return -1;
229             }
230 
231             GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
232 
233             for (auto gpuPerfInfo : gpuPerfInfos) {
234                 unsigned int gpuCounterBackSize = gpuCounter.size();
235                 gpuCounter.push_back(gpuPerfInfo);
236                 unsigned int gpuCounterSize = gpuCounter.size();
237                 if (gpuCounterSize <= gpuCounterBackSize) {
238                     WLOGE("gpuCounter data len error!");
239                     return -1;
240                 }
241                 GpuPerfInfo *newData = &gpuCounter[gpuCounterSize - 1];
242                 GpuPerfInfo *backData = &gpuCounter[gpuCounterSize - 2];
243                 if (newData == nullptr || backData == nullptr) {
244                     WLOGE("gpuCounter data pointer is null!");
245                     return -1;
246                 }
247                 long long durationTime = newData->startTime - backData->startTime;
248 
249                 // 如果两次数据间隔过短,则舍弃新数据
250                 if (durationTime < collectInterval) {
251                     WLOGE("Start time(%lld, %lld) make duration time(%lld) too short",
252                         newData->startTime, backData->startTime, durationTime);
253                     gpuCounter.pop_back();
254                     continue;
255                 }
256                 backData->duration = durationTime;
257                 std::string gpuPerfInfoItemStr = GetGpuPerfInfoItem(backData);
258                 gpuCounterInstance.GetGpuCounterData().push_back(gpuPerfInfoItemStr);
259                 gpuCounterInstance.GetGpuCounterSaveReportData().push_back(gpuPerfInfoItemStr);
260                 GetRealTime(backData);
261             }
262 
263             if (gpuPerfInfos[0].remainTime <= restartTime) {
264                 gpuCounterInstance.StartCollect(GpuCounter::GC_RESTART);
265             }
266             return 0;
267         }
268     }
269 }