• 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             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
129                 realtimeGpuPerfInfoData.gpuActive - gpuActiveTargetValue) + "_");
130             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
131                 realtimeGpuPerfInfoData.drawCalls - drawCallsTargetValue) + "_");
132             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
133                 realtimeGpuPerfInfoData.primitives - primitivesTargetValue) + "_");
134             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
135                 realtimeGpuPerfInfoData.vertexCounts - vertexCountsTargetValue) + "_");
136             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
137                 realtimeGpuPerfInfoData.totalInstruments - totalInstrumentsTargetValue) + "_");
138             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
139                 realtimeGpuPerfInfoData.memoryReadBandwidth - memoryReadBandwidthTargetValue) + "_");
140             gpuCounterInstance.AddGpuCounterRealtimeData(std::to_string(
141                 realtimeGpuPerfInfoData.memoryWriteBandwidth - memoryWriteBandwidthTargetValue) + "_");
142 
143             realtimeGpuPerfInfoData.gpuActive = gpuActiveTargetValue;
144             realtimeGpuPerfInfoData.drawCalls = drawCallsTargetValue;
145             realtimeGpuPerfInfoData.primitives = primitivesTargetValue;
146             realtimeGpuPerfInfoData.vertexCounts = vertexCountsTargetValue;
147             realtimeGpuPerfInfoData.totalInstruments = totalInstrumentsTargetValue;
148             realtimeGpuPerfInfoData.memoryReadBandwidth = memoryReadBandwidthTargetValue;
149             realtimeGpuPerfInfoData.memoryWriteBandwidth = memoryWriteBandwidthTargetValue;
150         }
151 
SplitSocketDataPercent()152         void GpuCounterCallbackImpl::SplitSocketDataPercent()
153         {
154             GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
155 
156             gpuCounterInstance.AddGpuCounterRealtimeData(
157                 std::to_string(realtimeGpuPerfInfoData.gpuLoadPercentage) + "_");
158             gpuCounterInstance.AddGpuCounterRealtimeData(
159                 std::to_string(realtimeGpuPerfInfoData.vertexLoadPercentage) + "_");
160             gpuCounterInstance.AddGpuCounterRealtimeData(
161                 std::to_string(realtimeGpuPerfInfoData.fragmentLoadPercentage) + "_");
162             gpuCounterInstance.AddGpuCounterRealtimeData(
163                 std::to_string(realtimeGpuPerfInfoData.computeLoadPercentage) + "_");
164             gpuCounterInstance.AddGpuCounterRealtimeData(
165                 std::to_string(realtimeGpuPerfInfoData.textureLoadPercentage) + ";");
166         }
167 
SplitSocketData()168         void GpuCounterCallbackImpl::SplitSocketData()
169         {
170             int32_t interval = realtimeGpuPerfInfoData.duration - maxDuration;
171             SplitSocketDataValue(interval);
172             SplitSocketDataPercent();
173             realtimeGpuPerfInfoData.duration = interval;
174         }
175 
GetRealTime(GpuPerfInfo * newData)176         void GpuCounterCallbackImpl::GetRealTime(GpuPerfInfo *newData)
177         {
178             GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
179 
180             JoinSocketData(newData);
181             if ((realtimeGpuPerfInfoData.duration == 0) || (newData->duration == 0)) {
182                 return;
183             }
184             gpuCounterInstance.GetRealtimeDataLock().lock();
185             while (realtimeGpuPerfInfoData.duration >= maxDuration) {
186                 SplitSocketData();
187             }
188             gpuCounterInstance.GetRealtimeDataLock().unlock();
189         }
190 
OnGpuData(std::vector<GpuPerfInfo> & gpuPerfInfos)191         int GpuCounterCallbackImpl::OnGpuData(std::vector <GpuPerfInfo> &gpuPerfInfos)
192         {
193             GpuCounter &gpuCounterInstance = GpuCounter::GetInstance();
194 
195             for (auto gpuPerfInfo : gpuPerfInfos) {
196                 unsigned int gpuCounterBackSize = gpuCounter.size();
197                 gpuCounter.push_back(gpuPerfInfo);
198                 unsigned int gpuCounterSize = gpuCounter.size();
199                 if (gpuCounterSize <= gpuCounterBackSize) {
200                     LOGE("gpuCounter data len error!");
201                     return -1;
202                 }
203                 GpuPerfInfo *newData = &gpuCounter[gpuCounterSize - 1];
204                 GpuPerfInfo *backData = &gpuCounter[gpuCounterSize - 2];
205                 long long durationTime = newData->startTime - backData->startTime;
206 
207                 // 如果两次数据间隔过短,则舍弃新数据
208                 if (durationTime < collectInterval) {
209                     LOGE("Start time(%lld, %lld) make duration time(%lld) too short",
210                          newData->startTime, backData->startTime, durationTime);
211                     gpuCounter.pop_back();
212                     continue;
213                 }
214 
215                 backData->duration = durationTime;
216 
217                 std::ostringstream oss;
218                 oss << backData->startTime << ","
219                     << backData->duration << ","
220                     << backData->gpuActive << ","
221                     << backData->drawCalls << ","
222                     << backData->primitives << ","
223                     << backData->vertexCounts << ","
224                     << backData->totalInstruments << ","
225                     << backData->gpuLoadPercentage << ","
226                     << backData->vertexLoadPercentage << ","
227                     << backData->fragmentLoadPercentage << ","
228                     << backData->computeLoadPercentage << ","
229                     << backData->textureLoadPercentage << ","
230                     << backData->memoryReadBandwidth << ","
231                     << backData->memoryWriteBandwidth << ","
232                     << backData->memoryBandwidthPercentage << ",";
233                 gpuCounterInstance.GetGpuCounterData().push_back(oss.str());
234                 gpuCounterInstance.GetGpuCounterSaveReportData().push_back(oss.str());
235 
236                 GetRealTime(backData);
237             }
238 
239             if (gpuPerfInfos[0].remainTime <= restartTime) {
240                 LOGI("remain time to restart");
241                 gpuCounterInstance.StartCollect(GpuCounter::GC_RESTART);
242             }
243             return 0;
244         }
245     }
246 }