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 "string" 18 #include "thread" 19 #include "fstream" 20 #include <iostream> 21 #include <dlfcn.h> 22 #include "include/sp_log.h" 23 #include "include/GpuCounter.h" 24 #include "include/service_plugin.h" 25 #include "interface/GpuCounterCallback.h" 26 #include "interface/GameServicePlugin.h" 27 28 namespace OHOS { 29 namespace SmartPerf { ItemData()30 std::map<std::string, std::string> GpuCounter::ItemData() 31 { 32 std::map<std::string, std::string> gpuCounterDataMap; 33 LOGI("GpuCounter:ItemData map size(%u)", gpuCounterDataMap.size()); 34 return gpuCounterDataMap; 35 } 36 StartExecutionOnce(bool isPause)37 void GpuCounter::StartExecutionOnce(bool isPause) 38 { 39 StartCollect(GpuCounter::GC_START); 40 } 41 FinishtExecutionOnce(bool isPause)42 void GpuCounter::FinishtExecutionOnce(bool isPause) 43 { 44 std::unique_lock<std::mutex> lock(gpuCounterLock); 45 SaveData(savePathDirectory_); 46 StopCollect(); 47 if (!isPause_) { 48 gpuCounterData.clear(); 49 } 50 } 51 SetSavePathDirectory(const std::string & dir)52 void GpuCounter::SetSavePathDirectory(const std::string& dir) 53 { 54 savePathDirectory_ = dir; 55 } 56 StartCollect(GcCollectType type)57 void GpuCounter::StartCollect(GcCollectType type) 58 { 59 if (frequency == 0) { 60 WLOGE("GpuCounter frequency is not set"); 61 return; 62 } 63 std::unique_ptr<GpuCounterCallback> gpuCounterCallback = std::make_unique<GpuCounterCallbackImpl>(); 64 65 // 1s 一次Gameservice回调 66 const int duration = 1000; 67 68 ServicePluginHandler &servicePluginHandler = ServicePluginHandler::GetInstance(); 69 void* handle = servicePluginHandler.GetSoHandler(ServicePluginHandler::ServicePluginType::GAME_PLUGIN); 70 if (!handle) { 71 WLOGE("Get service plugin handler failed."); 72 return; 73 } 74 75 typedef GameServicePlugin *(*GetServicePlugin)(); 76 GetServicePlugin servicePlugin = (GetServicePlugin)dlsym(handle, createPlugin.c_str()); 77 if (!servicePlugin) { 78 WLOGE("GameServicePlugin Error loading symbol"); 79 return; 80 } 81 82 if (type == GC_START && gcStatus == GC_INIT) { 83 if (!isPause_) { 84 gpuCounterData.clear(); 85 gpuCounterRealtimeData.clear(); 86 } 87 int ret = servicePlugin()->StartGetGpuPerfInfo(duration, frequency, std::move(gpuCounterCallback)); 88 if (ret == 0) { 89 gcStatus = GC_RUNNING; 90 } else { 91 WLOGE("GpuCounter call gameService error, ret = %d", ret); 92 } 93 } else if (type == GC_RESTART && gcStatus == GC_RUNNING) { 94 int ret = servicePlugin()->StartGetGpuPerfInfo(duration, frequency, std::move(gpuCounterCallback)); 95 if (ret != 0) { 96 WLOGE("GpuCounter call gameService error, ret = %d", ret); 97 } 98 } else { 99 WLOGE("GpuCounter state error, type: %d, state: %d", type, gcStatus); 100 } 101 } 102 SaveData(const std::string & path)103 void GpuCounter::SaveData(const std::string& path) 104 { 105 // device与editor采集都会走tcp stop时的SaveData,但是deivce同时会走FinishtExecutionOnce导致SaveData执行两次 106 // 目前device在第一次保存数据后会清空,第二次SaveData实际不生效 107 if (gcStatus != GC_RUNNING || gpuCounterData.size() <= 0 || path.empty()) { 108 return; 109 } 110 savePathDirectory_ = path; 111 char gpuCounterDataDirChar[PATH_MAX] = {0x00}; 112 if (realpath(path.c_str(), gpuCounterDataDirChar) == nullptr) { 113 WLOGE("data dir %s is nullptr", path.c_str()); 114 return; 115 } 116 std::string gpuCounterDataPath = std::string(gpuCounterDataDirChar) + "/gpu_counter.csv"; 117 std::ofstream outFile; 118 outFile.open(gpuCounterDataPath.c_str(), std::ios::out | std::ios::trunc); 119 if (!outFile.is_open()) { 120 WLOGE("open GpuCounter data file failed. %s", gpuCounterDataPath.c_str()); 121 return; 122 } 123 static const std::string title = "startTime," 124 "duration," 125 "gpuActive," 126 "drawCalls," 127 "primitives," 128 "vertexCounts," 129 "totalInstruments," 130 "gpuLoadPercentage," 131 "vertexLoadPercentage," 132 "fragmentLoadPercentage," 133 "computeLoadPercentage," 134 "textureLoadPercentage," 135 "memoryReadBandwidth," 136 "memoryWriteBandwidth," 137 "memoryBandwidthPercentage\r"; 138 outFile << title << std::endl; 139 std::unique_lock<std::mutex> lock(realtimeDataLock); 140 for (unsigned int i = 0; i < gpuCounterSaveReportData.size() - 1; i++) { 141 outFile << gpuCounterSaveReportData[i] << std::endl; 142 } 143 outFile.close(); 144 } 145 GetGpuCounterData()146 std::vector<std::string> &GpuCounter::GetGpuCounterData() 147 { 148 return gpuCounterData; 149 } 150 GetGpuCounterSaveReportData()151 std::vector<std::string> &GpuCounter::GetGpuCounterSaveReportData() 152 { 153 return gpuCounterSaveReportData; 154 } 155 GetGpuRealtimeData()156 std::map<std::string, std::string> GpuCounter::GetGpuRealtimeData() 157 { 158 std::unique_lock<std::mutex> lock(realtimeDataLock); 159 std::map<std::string, std::string> gpuCounterDataMap = {}; 160 if (gpuCounterRealtimeData.size() > 0) { 161 gpuCounterDataMap.insert({"gpuCounterData", gpuCounterRealtimeData}); 162 gpuCounterRealtimeData.clear(); 163 } 164 return gpuCounterDataMap; 165 } AddGpuCounterRealtimeData(const std::string & dataString)166 void GpuCounter::AddGpuCounterRealtimeData(const std::string& dataString) 167 { 168 std::unique_lock<std::mutex> lock(realtimeDataLock); 169 gpuCounterRealtimeData += dataString; 170 } 171 StopCollect()172 void GpuCounter::StopCollect() 173 { 174 if (gcStatus != GC_RUNNING) { 175 return; 176 } 177 ServicePluginHandler &servicePluginHandler = ServicePluginHandler::GetInstance(); 178 void* handle = servicePluginHandler.GetSoHandler(ServicePluginHandler::ServicePluginType::GAME_PLUGIN); 179 if (!handle) { 180 WLOGE("Get service plugin handler failed."); 181 return; 182 } 183 184 typedef GameServicePlugin *(*GetServicePlugin)(); 185 GetServicePlugin servicePlugin = (GetServicePlugin)dlsym(handle, createPlugin.c_str()); 186 if (!servicePlugin) { 187 WLOGE("GameServicePlugin Error loading symbol"); 188 return; 189 } 190 191 int ret = servicePlugin()->StopGetGpuPerfInfo(); 192 if (ret == 0) { 193 gcStatus = GC_INIT; 194 } 195 } 196 SetFrequency(const int & freq)197 void GpuCounter::SetFrequency(const int& freq) 198 { 199 frequency = freq; 200 } 201 GetGpuCounterLock()202 std::mutex &GpuCounter::GetGpuCounterLock() 203 { 204 return gpuCounterLock; 205 } 206 SetIsPause(bool isPause)207 void GpuCounter::SetIsPause(bool isPause) 208 { 209 isPause_ = isPause; 210 } 211 } 212 }