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 23namespace OHOS { 24 namespace SmartPerf { 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 49 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 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 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 87 void GpuCounterCallbackImpl::JoinSocketData(GpuPerfInfo *newData) 88 { 89 JoinSocketDataValue(newData); 90 JoinSocketDataPercent(newData); 91 92 realtimeGpuPerfInfoData.duration += newData->duration; 93 } 94 95 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 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 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 168 void GpuCounterCallbackImpl::SplitSocketData() 169 { 170 int32_t interval = realtimeGpuPerfInfoData.duration - maxDuration; 171 SplitSocketDataValue(interval); 172 SplitSocketDataPercent(); 173 realtimeGpuPerfInfoData.duration = interval; 174 } 175 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 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}