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/GpuCounterCallback.h" 25 26namespace OHOS { 27 namespace SmartPerf { 28 std::map<std::string, std::string> GpuCounter::ItemData() 29 { 30 return std::map<std::string, std::string>(); 31 } 32 void* GpuCounter::GetSoHandle() 33 { 34 char soFilePathChar[PATH_MAX] = {0x00}; 35 if ((realpath(PLUGIN_SO_PATH.c_str(), soFilePathChar) == nullptr)) { 36 LOGE("%s is not exist.", PLUGIN_SO_PATH.c_str()); 37 return nullptr; 38 } 39 40 void* handle = dlopen(soFilePathChar, RTLD_LAZY); 41 if (!handle) { 42 LOGI("open GpuCounterPlugin so file error."); 43 return nullptr; 44 } 45 46 return handle; 47 } 48 void GpuCounter::StartCollect(GcCollectType type) 49 { 50 std::unique_ptr<GpuCounterCallback> gpuCounterCallback = std::make_unique<GpuCounterCallbackImpl>(); 51 52 const int duration = 1000; 53 54 void* handle = GetSoHandle(); 55 if (!handle) { 56 return; 57 } 58 59 typedef GpuCounterPlugin *(*GetGpuCounterPlugin)(); 60 GetGpuCounterPlugin startGetGpuPerfInfo = (GetGpuCounterPlugin)dlsym(handle, CREATE_PLUGIN.c_str()); 61 62 if (type == GC_START && gcStatus == GC_INIT) { 63 gpuCounterData.clear(); 64 gpuCounterRealtimeData.clear(); 65 int ret = startGetGpuPerfInfo()->StartGetGpuPerfInfo(duration, std::move(gpuCounterCallback)); 66 if (ret == 0) { 67 gcStatus = GC_RUNNING; 68 LOGI("GpuCounter collect start."); 69 } else { 70 LOGE("GpuCounter call gameService error, ret = %d", ret); 71 } 72 } else if (type == GC_RESTART && gcStatus == GC_RUNNING) { 73 int ret = startGetGpuPerfInfo()->StartGetGpuPerfInfo(duration, std::move(gpuCounterCallback)); 74 if (ret == 0) { 75 LOGI("GpuCounter recollect start."); 76 } else { 77 LOGE("GpuCounter call gameService error, ret = %d", ret); 78 } 79 } else { 80 LOGE("GpuCounter state error, type: %d, state: %d", type, gcStatus); 81 } 82 } 83 84 void GpuCounter::SaveData(std::string path) 85 { 86 if (gcStatus != GC_RUNNING || gpuCounterData.size() <= 0) { 87 return; 88 } 89 LOGI("GpuCounter collect stop."); 90 char gpuCounterDataDirChar[PATH_MAX] = {0x00}; 91 if (realpath(path.c_str(), gpuCounterDataDirChar) == nullptr) { 92 LOGE("data dir %s is nullptr", path.c_str()); 93 return; 94 } 95 std::string gpuCounterDataPath = std::string(gpuCounterDataDirChar) + "/gpu_counter.csv"; 96 std::ofstream outFile; 97 std::mutex mtx; 98 mtx.lock(); 99 outFile.open(gpuCounterDataPath.c_str(), std::ios::out | std::ios::trunc); 100 if (!outFile.is_open()) { 101 LOGE("open GpuCounter data file failed."); 102 return; 103 } 104 std::string title = "startTime," 105 "duration," 106 "gpuActive," 107 "drawCalls," 108 "primitives," 109 "vertexCounts," 110 "totalInstruments," 111 "gpuLoadPercentage," 112 "vertexLoadPercentage," 113 "fragmentLoadPercentage," 114 "computeLoadPercentage," 115 "textureLoadPercentage," 116 "memoryReadBandwidth," 117 "memoryWriteBandwidth," 118 "memoryBandwidthPercentage\r"; 119 outFile << title << std::endl; 120 for (unsigned int i = 0; i < gpuCounterSaveReportData.size() - 1; i++) { 121 outFile << gpuCounterSaveReportData[i] << std::endl; 122 } 123 outFile.close(); 124 mtx.unlock(); 125 } 126 127 std::vector<std::string> &GpuCounter::GetGpuCounterData() 128 { 129 return gpuCounterData; 130 } 131 132 std::vector<std::string> &GpuCounter::GetGpuCounterSaveReportData() 133 { 134 return gpuCounterSaveReportData; 135 } 136 137 std::mutex &GpuCounter::GetRealtimeDataLock() 138 { 139 return realtimeDataLock; 140 } 141 142 std::string &GpuCounter::GetGpuCounterRealtimeData() 143 { 144 return gpuCounterRealtimeData; 145 } 146 void GpuCounter::AddGpuCounterRealtimeData(std::string dataString) 147 { 148 gpuCounterRealtimeData += dataString; 149 } 150 151 void GpuCounter::GetGpuRealtimeData(std::map<std::string, std::string> &dataMap) 152 { 153 if (gpuCounterRealtimeData.size() > 0) { 154 std::map<std::string, std::string> gpuCounterRealtimeDataMap; 155 gpuCounterRealtimeDataMap["gpuCounterData"] = gpuCounterRealtimeData; 156 realtimeDataLock.lock(); 157 dataMap.insert(gpuCounterRealtimeDataMap.begin(), gpuCounterRealtimeDataMap.end()); 158 realtimeDataLock.unlock(); 159 gpuCounterRealtimeData.clear(); 160 } 161 } 162 163 void GpuCounter::StopCollect() 164 { 165 if (gcStatus != GC_RUNNING) { 166 return; 167 } 168 169 void* handle = GetSoHandle(); 170 if (!handle) { 171 return; 172 } 173 174 typedef GpuCounterPlugin *(*GetGpuCounterPlugin)(); 175 GetGpuCounterPlugin startGetGpuPerfInfo = (GetGpuCounterPlugin)dlsym(handle, CREATE_PLUGIN.c_str()); 176 177 int ret = startGetGpuPerfInfo()->StopGetGpuPerfInfo(); 178 if (ret == 0) { 179 gcStatus = GC_INIT; 180 LOGI("GpuCounter collect finish."); 181 } 182 } 183 } 184}