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 GpuCounter &gpuCounterInstance = GpuCounter::GetInstance(); 180 181 JoinSocketData(newData); 182 if ((realtimeGpuPerfInfoData.duration == 0) || (newData->duration == 0)) { 183 return; 184 } 185 gpuCounterInstance.GetRealtimeDataLock().lock(); 186 while (realtimeGpuPerfInfoData.duration >= maxDuration) { 187 SplitSocketData(); 188 } 189 gpuCounterInstance.GetRealtimeDataLock().unlock(); 190 } 191 OnGpuData(std::vector<GpuPerfInfo> & gpuPerfInfos)192 int GpuCounterCallbackImpl::OnGpuData(std::vector <GpuPerfInfo> &gpuPerfInfos) 193 { 194 GpuCounter &gpuCounterInstance = GpuCounter::GetInstance(); 195 196 for (auto gpuPerfInfo : gpuPerfInfos) { 197 unsigned int gpuCounterBackSize = gpuCounter.size(); 198 gpuCounter.push_back(gpuPerfInfo); 199 unsigned int gpuCounterSize = gpuCounter.size(); 200 if (gpuCounterSize <= gpuCounterBackSize) { 201 LOGE("gpuCounter data len error!"); 202 return -1; 203 } 204 GpuPerfInfo *newData = &gpuCounter[gpuCounterSize - 1]; 205 GpuPerfInfo *backData = &gpuCounter[gpuCounterSize - 2]; 206 long long durationTime = newData->startTime - backData->startTime; 207 208 // 如果两次数据间隔过短,则舍弃新数据 209 if (durationTime < collectInterval) { 210 LOGE("Start time(%lld, %lld) make duration time(%lld) too short", 211 newData->startTime, backData->startTime, durationTime); 212 gpuCounter.pop_back(); 213 continue; 214 } 215 216 backData->duration = durationTime; 217 218 std::ostringstream oss; 219 oss << backData->startTime << "," 220 << backData->duration << "," 221 << backData->gpuActive << "," 222 << backData->drawCalls << "," 223 << backData->primitives << "," 224 << backData->vertexCounts << "," 225 << backData->totalInstruments << "," 226 << backData->gpuLoadPercentage << "," 227 << backData->vertexLoadPercentage << "," 228 << backData->fragmentLoadPercentage << "," 229 << backData->computeLoadPercentage << "," 230 << backData->textureLoadPercentage << "," 231 << backData->memoryReadBandwidth << "," 232 << backData->memoryWriteBandwidth << "," 233 << backData->memoryBandwidthPercentage << ","; 234 gpuCounterInstance.GetGpuCounterData().push_back(oss.str()); 235 gpuCounterInstance.GetGpuCounterSaveReportData().push_back(oss.str()); 236 237 GetRealTime(backData); 238 } 239 240 if (gpuPerfInfos[0].remainTime <= restartTime) { 241 gpuCounterInstance.StartCollect(GpuCounter::GC_RESTART); 242 } 243 return 0; 244 } 245 } 246 }