diff --git a/smartperf_device/device_command/colltector/src/DDR.cpp b/smartperf_device/device_command/colltector/src/DDR.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1d78b2c38ff52abdf0420b85cf6a8d617b5e67ac --- /dev/null +++ b/smartperf_device/device_command/colltector/src/DDR.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "include/sp_utils.h" +#include "include/DDR.h" +#include "include/sp_log.h" +namespace OHOS { +namespace SmartPerf { +std::map DDR::ItemData() +{ + std::map result; + result["ddrFrequency"] = std::to_string(GetDdrFreq()).empty() ? "NA" : std::to_string(GetDdrFreq()); + LOGI("DDR:ItemData map size(%u)", result.size()); + return result; +} +long long DDR::GetDdrFreq() +{ + long long curFreq = -1; + std::string ddrfreq; + if (!rkFlag) { + SPUtils::LoadFile(ddrCurFreqPath, ddrfreq); + } else { + SPUtils::LoadFile(ddrCurFreqRkPath, ddrfreq); + } + curFreq = SPUtilesTye::StringToSometype(ddrfreq.c_str()); + return curFreq; +} +void DDR::SetRkFlag() +{ + rkFlag = true; +} +} +} diff --git a/smartperf_device/device_command/colltector/src/Dubai.cpp b/smartperf_device/device_command/colltector/src/Dubai.cpp new file mode 100644 index 0000000000000000000000000000000000000000..abbd47d82be7f6f5494ad06748003041a43b82ac --- /dev/null +++ b/smartperf_device/device_command/colltector/src/Dubai.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include "include/sp_utils.h" +#include "include/Dubai.h" +#include "include/sp_log.h" +#include "include/common.h" +namespace OHOS { +namespace SmartPerf { +void Dubai::DumpDubaiBegin() +{ + std::string result; + std::string dumpBubaiB = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_DUBAI_B); + SPUtils::LoadCmd(dumpBubaiB, result); + LOGD("Dubai::DumpDubaiBegin"); +} +void Dubai::DumpDubaiFinish() +{ + std::string result; + std::string dumpBubaiF = HIDUMPER_CMD_MAP.at(HidumperCmd::DUMPER_DUBAI_F); + SPUtils::LoadCmd(dumpBubaiF, result); + LOGD("Dubai::DumpDubaiFinish"); +} + +void Dubai::MoveDubaiDb() +{ + std::string result; + const std::string dubaiXpower = "/data/service/el2/100/xpower/dubai.db"; + const std::string Database = "/data/app/el2/100/database/"; + const std::string PkgEntry = "/entry/rdb"; + const std::string cpDubai = "cp " + dubaiXpower + " " + Database + dubaiPkgName + PkgEntry; + const std::string dubaiPathChmod = "chmod 777 " + Database + dubaiPkgName + PkgEntry + "/dubai.db"; + LOGD("cpDubai: (%s), dubaiPathChmod: (%s)", + cpDubai.c_str(), dubaiPathChmod.c_str()); + if (!IsFileAccessible(dubaiXpower)) { + sleep(1); + } + SPUtils::LoadCmd(cpDubai, result); + if (result.empty()) { + LOGE("Dubai::Copy dubai.db failed"); + } else { + SPUtils::LoadCmd(dubaiPathChmod, result); + } +} + +void Dubai::MoveDubaiDb(const std::string &path) +{ + std::string result; + const std::string dubaiLocalPath = "/data/local/tmp/dubai"; + SPUtils::CreateDir(dubaiLocalPath); + const std::string cpDubai = "cp " + path + " " + dubaiLocalPath; + const std::string dubaiPathChmod = "chmod 777 " + dubaiLocalPath + "dubai.db"; + LOGD("cpDubai:(%s), dubaiPathChmod:(%s)", + cpDubai.c_str(), dubaiPathChmod.c_str()); + if (!IsFileAccessible(path)) { + sleep(1); + } + SPUtils::LoadCmd(cpDubai, result); + if (dubaiLocalPath.empty()) { + LOGE("Dubai::Copy dubai.db failed"); + } else { + SPUtils::LoadCmd(dubaiPathChmod, result); + } +} + +void Dubai::CallBeginAndFinish() +{ + DumpDubaiBegin(); + DumpDubaiFinish(); +} + +std::string Dubai::CallMoveDubaiDbFinished() +{ + std::string dubaiMoveFinish; + if (isDumpDubaiFinish) { + MoveDubaiDb(); + } + dubaiMoveFinish = "get_dubai_db"; + return dubaiMoveFinish; +} + +bool Dubai::IsFileAccessible(const std::string &filename) +{ + char duBaiRealPath[PATH_MAX] = {0x00}; + if (realpath(filename.c_str(), duBaiRealPath) == nullptr) { + std::cout << "" << std::endl; + } + std::ifstream file(duBaiRealPath); + return file.good(); +} +} +} \ No newline at end of file diff --git a/smartperf_device/device_command/colltector/src/FileDescriptor.cpp b/smartperf_device/device_command/colltector/src/FileDescriptor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9a7fa52a928c6aff95e38909d052eb7e41db2fcc --- /dev/null +++ b/smartperf_device/device_command/colltector/src/FileDescriptor.cpp @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include "include/FileDescriptor.h" +#include "include/sp_utils.h" +#include "include/sp_log.h" + +namespace fs = std::filesystem; +namespace OHOS { +namespace SmartPerf { +const size_t FDSRESERVE_SIZE = 512; +const size_t FDTOTALSRESERVE_SIZE = 1024; +std::map FileDescriptor::ItemData() +{ + std::map result; + std::string& fds = result["fds"]; + std::string& fdTotal = result["fdTotal"]; + fds.reserve(FDSRESERVE_SIZE); + fdTotal.reserve(FDTOTALSRESERVE_SIZE); + idNum = processId.size(); + for (size_t i = 0; i < idNum; i++) { + GetFds(processId[i], fds, fdTotal); + } +#ifndef FUZZ_TEST + LOGD("FileDescriptor::ItemData %s %s", fds.c_str(), fdTotal.c_str()); +#endif + return result; +} + +void FileDescriptor::SetPackageName(const std::string &pName) +{ + packageName = pName; +} + +void FileDescriptor::SetProcessId(const std::string &pid) +{ + processId.clear(); + SPUtils::StrSplit(pid, " ", processId); +} + +void FileDescriptor::GetFds(const std::string &pid, std::string &fds, std::string &fdTotal) +{ + std::string directoryPath = "/proc/"; + directoryPath.append(pid).append("/fd/"); + int cnt = 0; + std::error_code ec; + if (fs::exists(directoryPath) && fs::is_directory(directoryPath)) { + fs::directory_iterator dir_iter(directoryPath, ec); + if (ec) { +#ifndef FUZZ_TEST + LOGD("Get fds info fail (%s)", ec.message().c_str()); + fds.append(pid).append(":").append("0"); + fdTotal.append(pid).append(":").append("0").append("|"); +#endif + return; + } + fds.append(pid).append(":"); + for (const auto &entry : dir_iter) { + std::string fileSymlink = fs::read_symlink(directoryPath + entry.path().filename().string(), ec); + if (ec) { +#ifndef FUZZ_TEST + LOGD("Get (%s) info fail (%s)", entry.path().c_str(), ec.message().c_str()); + break; +#endif + } + ++cnt; + fds.append(entry.path().filename().string()).append("->").append(fileSymlink).append(" "); + } + fdTotal.append(pid).append(":").append(std::to_string(cnt)); + if (idNum > 1) { + fds.append("|"); + fdTotal.append("|"); + } + } else { + processId.erase(std::remove(processId.begin(), processId.end(), pid), processId.end()); +#ifndef FUZZ_TEST + LOGD("(%s) Not exist.", directoryPath.c_str()); +#endif + } +} + +void FileDescriptor::SetProcessIdForFuzzTest(const std::vector &pid) +{ + processId = pid; +} +} +} \ No newline at end of file diff --git a/smartperf_device/device_command/colltector/src/GPU.cpp b/smartperf_device/device_command/colltector/src/GPU.cpp new file mode 100644 index 0000000000000000000000000000000000000000..fb53299a35227ad749b902d29741688395a5dcff --- /dev/null +++ b/smartperf_device/device_command/colltector/src/GPU.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "include/GPU.h" +#include +#include "include/sp_utils.h" +#include "gpu_collector.h" +#include "collect_result.h" +#include "include/sp_log.h" + +using namespace OHOS::HiviewDFX; +using namespace OHOS::HiviewDFX::UCollectUtil; +using namespace OHOS::HiviewDFX::UCollect; + +namespace OHOS { +namespace SmartPerf { +std::map GPU::ItemData() +{ + std::map result; + int32_t freq; + float load; + if (!rkFlag) { + freq = GetGpuFreq(); + load = GetGpuLoad(); + } else { + freq = GetRkGpuFreq(); + load = GetRkGpuLoad(); + } + result["gpuFrequency"] = std::to_string(freq); + result["gpuLoad"] = std::to_string(load); + if (result.find("gpuFrequency") != result.end() && result["gpuFrequency"].empty()) { + result["gpuFrequency"] = "NA"; + result["gpuLoad"] = "NA"; + } + LOGI("GPU:ItemData map size(%u)", result.size()); + return result; +} + +int GPU::GetGpuFreq() +{ + std::shared_ptr collector = GpuCollector::Create(); + CollectResult result = collector->CollectGpuFrequency(); + return result.data.curFeq; +} + +float GPU::GetGpuLoad() +{ + std::shared_ptr collector = GpuCollector::Create(); + CollectResult result = collector->CollectSysGpuLoad(); + return float(result.data.gpuLoad); +} + +int32_t GPU::GetRkGpuFreq() +{ + const std::string gpuFreqPath = "/sys/class/devfreq/fde60000.gpu/cur_freq"; + std::string rkFreq; + SPUtils::LoadFile(gpuFreqPath, rkFreq); + return SPUtilesTye::StringToSometype(rkFreq); +} + +float GPU::GetRkGpuLoad() +{ + const std::string gpuLoadPath = "/sys/class/devfreq/fde60000.gpu/load"; + std::string rkLoad; + SPUtils::LoadFile(gpuLoadPath, rkLoad); + size_t len = rkLoad.length(); + if (len > 0) { + rkLoad = rkLoad.substr(0, len - 1); + } + return SPUtilesTye::StringToSometype(rkLoad); +} + +void GPU::SetRkFlag() +{ + rkFlag = true; +} +} +} diff --git a/smartperf_device/device_command/colltector/src/GameEvent.cpp b/smartperf_device/device_command/colltector/src/GameEvent.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9bd33abc1d5b073e679761d0215db22efe8e7acb --- /dev/null +++ b/smartperf_device/device_command/colltector/src/GameEvent.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "include/GameEvent.h" +#include "interface/GameServicePlugin.h" + +#include +#include +#include "include/service_plugin.h" +#include +#include +#include + +namespace OHOS { +namespace SmartPerf { +void GameEventCallbackImpl::OnGameEvent(int32_t type, std::map ¶ms) +{ + for (auto &item : params) { + GameEvent::GetInstance().GetGameEventItemData()[item.first] = item.second; + } +} + +std::map GameEvent::ItemData() +{ + LOGI("GameEvent:ItemData map size(%u)", gameEventItemData.size()); + return gameEventItemData; +} + +std::map &GameEvent::GetGameEventItemData() +{ + return gameEventItemData; +} + +void GameEvent::StartExecutionOnce(bool isPause) +{ + if (isPause) { + return; + } + RegisterGameEvent(); +} + +void GameEvent::FinishtExecutionOnce(bool isPause) +{ + if (isPause) { + return; + } + UnregisterGameEvent(); +} + +int GameEvent::RegisterGameEvent() +{ + if (isRegister) { + WLOGI("GameEvent::RegisterGameEvent, already register"); + return 0; + } + WLOGI("GameEvent::RegisterGameEvent"); + std::unique_ptr gameEventCallback = std::make_unique(); + ServicePluginHandler &servicePluginHandler = ServicePluginHandler::GetInstance(); + void* handle = servicePluginHandler.GetSoHandler(ServicePluginHandler::ServicePluginType::GAME_PLUGIN); + if (!handle) { + WLOGE("Get service plugin handler failed."); + return -1; + } + typedef GameServicePlugin *(*GetServicePlugin)(); + GetServicePlugin servicePlugin = (GetServicePlugin)dlsym(handle, createPlugin.c_str()); + if (!servicePlugin) { + WLOGE("GameServicePlugin Error loading symbol"); + return -1; + } + + int ret = servicePlugin()->RegisterGameEventListener(std::move(gameEventCallback)); + if (ret == 0) { + isRegister = true; + WLOGI("GameEvent::ItemData, RegisterGameEventListener success"); + } else { + WLOGE("GameEvent::ItemData, RegisterGameEventListener failed"); + } + return ret; +} + +int GameEvent::UnregisterGameEvent() +{ + if (!isRegister) { + return 0; + } + WLOGI("GameEvent::UnregisterGameEvent"); + ServicePluginHandler &servicePluginHandler = ServicePluginHandler::GetInstance(); + void* handle = servicePluginHandler.GetSoHandler(ServicePluginHandler::ServicePluginType::GAME_PLUGIN); + if (!handle) { + WLOGE("Get service plugin handler failed."); + return -1; + } + typedef GameServicePlugin *(*GetServicePlugin)(); + GetServicePlugin servicePlugin = (GetServicePlugin)dlsym(handle, createPlugin.c_str()); + if (!servicePlugin) { + WLOGE("GameServicePlugin Error loading symbol"); + return -1; + } + + int ret = servicePlugin()->UnregisterGameEventListener(); + if (ret == 0) { + isRegister = false; + WLOGI("GameEvent::ItemData, UnregisterGameEventListener success"); + } else { + WLOGE("GameEvent::ItemData, UnregisterGameEventListener failed"); + } + return ret; +} + +} // namespace SmartPerf +} // namespace OHOS \ No newline at end of file diff --git a/smartperf_device/device_command/colltector/src/GpuCounter.cpp b/smartperf_device/device_command/colltector/src/GpuCounter.cpp new file mode 100644 index 0000000000000000000000000000000000000000..86ed8c0439ed8c1eef169107342c43f7db391378 --- /dev/null +++ b/smartperf_device/device_command/colltector/src/GpuCounter.cpp @@ -0,0 +1,212 @@ +/* + * Copyright (C) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "chrono" +#include "string" +#include "thread" +#include "fstream" +#include +#include +#include "include/sp_log.h" +#include "include/GpuCounter.h" +#include "include/service_plugin.h" +#include "interface/GpuCounterCallback.h" +#include "interface/GameServicePlugin.h" + +namespace OHOS { + namespace SmartPerf { + std::map GpuCounter::ItemData() + { + std::map gpuCounterDataMap; + LOGI("GpuCounter:ItemData map size(%u)", gpuCounterDataMap.size()); + return gpuCounterDataMap; + } + + void GpuCounter::StartExecutionOnce(bool isPause) + { + StartCollect(GpuCounter::GC_START); + } + + void GpuCounter::FinishtExecutionOnce(bool isPause) + { + std::unique_lock lock(gpuCounterLock); + SaveData(savePathDirectory_); + StopCollect(); + if (!isPause_) { + gpuCounterData.clear(); + } + } + + void GpuCounter::SetSavePathDirectory(const std::string& dir) + { + savePathDirectory_ = dir; + } + + void GpuCounter::StartCollect(GcCollectType type) + { + if (frequency == 0) { + WLOGE("GpuCounter frequency is not set"); + return; + } + std::unique_ptr gpuCounterCallback = std::make_unique(); + + // 1s 一次Gameservice回调 + const int duration = 1000; + + ServicePluginHandler &servicePluginHandler = ServicePluginHandler::GetInstance(); + void* handle = servicePluginHandler.GetSoHandler(ServicePluginHandler::ServicePluginType::GAME_PLUGIN); + if (!handle) { + WLOGE("Get service plugin handler failed."); + return; + } + + typedef GameServicePlugin *(*GetServicePlugin)(); + GetServicePlugin servicePlugin = (GetServicePlugin)dlsym(handle, createPlugin.c_str()); + if (!servicePlugin) { + WLOGE("GameServicePlugin Error loading symbol"); + return; + } + + if (type == GC_START && gcStatus == GC_INIT) { + if (!isPause_) { + gpuCounterData.clear(); + gpuCounterRealtimeData.clear(); + } + int ret = servicePlugin()->StartGetGpuPerfInfo(duration, frequency, std::move(gpuCounterCallback)); + if (ret == 0) { + gcStatus = GC_RUNNING; + } else { + WLOGE("GpuCounter call gameService error, ret = %d", ret); + } + } else if (type == GC_RESTART && gcStatus == GC_RUNNING) { + int ret = servicePlugin()->StartGetGpuPerfInfo(duration, frequency, std::move(gpuCounterCallback)); + if (ret != 0) { + WLOGE("GpuCounter call gameService error, ret = %d", ret); + } + } else { + WLOGE("GpuCounter state error, type: %d, state: %d", type, gcStatus); + } + } + + void GpuCounter::SaveData(const std::string& path) + { + // device与editor采集都会走tcp stop时的SaveData,但是deivce同时会走FinishtExecutionOnce导致SaveData执行两次 + // 目前device在第一次保存数据后会清空,第二次SaveData实际不生效 + if (gcStatus != GC_RUNNING || gpuCounterData.size() <= 0 || path.empty()) { + return; + } + savePathDirectory_ = path; + char gpuCounterDataDirChar[PATH_MAX] = {0x00}; + if (realpath(path.c_str(), gpuCounterDataDirChar) == nullptr) { + WLOGE("data dir %s is nullptr", path.c_str()); + return; + } + std::string gpuCounterDataPath = std::string(gpuCounterDataDirChar) + "/gpu_counter.csv"; + std::ofstream outFile; + outFile.open(gpuCounterDataPath.c_str(), std::ios::out | std::ios::trunc); + if (!outFile.is_open()) { + WLOGE("open GpuCounter data file failed. %s", gpuCounterDataPath.c_str()); + return; + } + static const std::string title = "startTime," + "duration," + "gpuActive," + "drawCalls," + "primitives," + "vertexCounts," + "totalInstruments," + "gpuLoadPercentage," + "vertexLoadPercentage," + "fragmentLoadPercentage," + "computeLoadPercentage," + "textureLoadPercentage," + "memoryReadBandwidth," + "memoryWriteBandwidth," + "memoryBandwidthPercentage\r"; + outFile << title << std::endl; + std::unique_lock lock(realtimeDataLock); + for (unsigned int i = 0; i < gpuCounterSaveReportData.size() - 1; i++) { + outFile << gpuCounterSaveReportData[i] << std::endl; + } + outFile.close(); + } + + std::vector &GpuCounter::GetGpuCounterData() + { + return gpuCounterData; + } + + std::vector &GpuCounter::GetGpuCounterSaveReportData() + { + return gpuCounterSaveReportData; + } + + std::map GpuCounter::GetGpuRealtimeData() + { + std::unique_lock lock(realtimeDataLock); + std::map gpuCounterDataMap = {}; + if (gpuCounterRealtimeData.size() > 0) { + gpuCounterDataMap.insert({"gpuCounterData", gpuCounterRealtimeData}); + gpuCounterRealtimeData.clear(); + } + return gpuCounterDataMap; + } + void GpuCounter::AddGpuCounterRealtimeData(const std::string& dataString) + { + std::unique_lock lock(realtimeDataLock); + gpuCounterRealtimeData += dataString; + } + + void GpuCounter::StopCollect() + { + if (gcStatus != GC_RUNNING) { + return; + } + ServicePluginHandler &servicePluginHandler = ServicePluginHandler::GetInstance(); + void* handle = servicePluginHandler.GetSoHandler(ServicePluginHandler::ServicePluginType::GAME_PLUGIN); + if (!handle) { + WLOGE("Get service plugin handler failed."); + return; + } + + typedef GameServicePlugin *(*GetServicePlugin)(); + GetServicePlugin servicePlugin = (GetServicePlugin)dlsym(handle, createPlugin.c_str()); + if (!servicePlugin) { + WLOGE("GameServicePlugin Error loading symbol"); + return; + } + + int ret = servicePlugin()->StopGetGpuPerfInfo(); + if (ret == 0) { + gcStatus = GC_INIT; + } + } + + void GpuCounter::SetFrequency(const int& freq) + { + frequency = freq; + } + + std::mutex &GpuCounter::GetGpuCounterLock() + { + return gpuCounterLock; + } + + void GpuCounter::SetIsPause(bool isPause) + { + isPause_ = isPause; + } + } +} \ No newline at end of file diff --git a/smartperf_device/device_command/colltector/src/cpu_info.cpp b/smartperf_device/device_command/colltector/src/cpu_info.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8b3d21f8e163c25c29354814ea18d47e9a0ca796 --- /dev/null +++ b/smartperf_device/device_command/colltector/src/cpu_info.cpp @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cpu_info.h" +#include "sp_utils.h" + +#include +#include +#include +#include +#include +#include "sp_log.h" +namespace OHOS { +namespace SmartPerf { +namespace { +const std::string HIPERF_CMD = "/bin/hiperf stat -e hw-instructions,hw-cpu-cycles -d 1 -i 500 "; +} + +std::map CPUInfo::ItemData() +{ + Stop(); + std::map result; + GetCpuInfoBuffer(result); + Start(); + LOGI("CPUInfo:ItemData map size(%u)", result.size()); + return result; +} + +void CPUInfo::GetCpuInfoBuffer(std::map &bufferResult) +{ + std::istringstream stream(buffer_); + std::string line; + uint64_t cpu_cycles_total = 0; + uint64_t instructions_total = 0; + double cpi_total = 0.0; + size_t cpu_cycles_count = 0; + size_t instructions_count = 0; + size_t cpi_count = 0; + auto trim = [](std::string& s) { + s.erase(0, s.find_first_not_of(" \t")); + s.erase(s.find_last_not_of(" \t") + 1); + }; + auto findData = [](const std::string& targetStr, auto& total, auto& count) { + size_t count_start = targetStr.find_first_not_of(" \t"); + size_t count_end = targetStr.find(" ", count_start); + std::string number_str = targetStr.substr(count_start, count_end - count_start); + number_str.erase(std::remove(number_str.begin(), number_str.end(), ','), number_str.end()); + total += SPUtilesTye::StringToSometype(number_str); + ++count; + }; + while (std::getline(stream, line)) { + HandleCpuInfoData(line, cpu_cycles_total, cpu_cycles_count, instructions_count, + cpi_count, cpi_total); + } + cpu_cycles_count == 0 ? "" : + bufferResult[SPUtils::GetProductName() + "-cpu-cycles"] = + std::to_string(static_cast(cpu_cycles_total) / cpu_cycles_count); + instructions_count == 0 ? "" : + bufferResult[SPUtils::GetProductName() + "-instructions"] = + std::to_string(static_cast(instructions_total) / instructions_count); + cpi_count == 0 ? "" : bufferResult["cycles per instruction"] = std::to_string(cpi_total / cpi_count); +} + +void CPUInfo::HandleCpuInfoData(std::string line, uint64_t cpu_cycles_total, size_t cpu_cycles_count, + size_t instructions_count, size_t cpi_count, double cpi_total) +{ + if (line.find(SPUtils::GetProductName() + "-cpu-cycles") != std::string::npos) { + findData(line, cpu_cycles_total, cpu_cycles_count); + } + if (line.find(SPUtils::GetProductName() + "-instructions") != std::string::npos) { + findData(line, instructions_total, instructions_count); + size_t comment_pos = line.find("|"); + if (comment_pos != std::string::npos) { + std::string comment = line.substr(comment_pos + 1); + trim(comment); + size_t cpi_pos = comment.find("cycles per instruction"); + if (cpi_pos != std::string::npos) { + size_t number_end = comment.find(" ", 0); + std::string cpi_str = comment.substr(0, number_end); + cpi_total += SPUtilesTye::StringToSometype(cpi_str); + ++cpi_count; + } + } + } +} + +void CPUInfo::StartExecutionOnce(bool isPause) +{ + (void)isPause; + Stop(); + hiperfCmd_ = HIPERF_CMD; + if (pids_.empty()) { + hiperfCmd_ += "-a"; + } else { + hiperfCmd_ += "-p " + pids_[0]; + } + + running_ = true; + th_ = std::thread([this]() { + while (running_) { + buffer_.clear(); + std::unique_ptr pipe(popen(hiperfCmd_.c_str(), "r"), pclose); + constexpr int lineSize = 1024; + std::array chunk; + while (fgets(chunk.data(), chunk.size(), pipe.get()) != nullptr) { + buffer_.append(chunk.data()); + } + + if (!running_) { + return; + } + std::unique_lock lock(mtx_); + cond_.wait(lock); + } + }); + sleep(1); +} + +void CPUInfo::FinishtExecutionOnce(bool isPause) +{ + (void)isPause; + running_ = false; + Stop(); + cond_.notify_all(); + if (th_.joinable()) { + th_.join(); + } +} + +void CPUInfo::SetPids(const std::string& pids) +{ + pids_.clear(); + SPUtils::StrSplit(pids, " ", pids_); +} + +void CPUInfo::Start() +{ + cond_.notify_all(); +} + +void CPUInfo::Stop() +{ + std::system("killall hiperf > /data/local/tmp/cpu_temp_error 2>&1"); + std::remove("/data/local/tmp/cpu_temp_error"); +} +} +} \ No newline at end of file diff --git a/smartperf_device/device_command/colltector/src/effective.cpp b/smartperf_device/device_command/colltector/src/effective.cpp new file mode 100644 index 0000000000000000000000000000000000000000..2d741c8fee50ea82cded5fe903095617da294565 --- /dev/null +++ b/smartperf_device/device_command/colltector/src/effective.cpp @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "effective.h" +#include "FPS.h" +#include "sp_utils.h" +#include "sp_log.h" +#include "common.h" + +namespace { +constexpr long long RM_1000000 = 1000000; +constexpr long long RM_5000 = 5000; +constexpr long long RM_0 = 0; +} +namespace OHOS { +namespace SmartPerf { +std::map Effective::ItemData() +{ + std::map templateMap; + + FpsCurrentFpsTime fcf = FPS::GetInstance().GetFpsCurrentFpsTime(); + long long nowTime = SPUtils::GetCurTime(); + long long curframeTime = fcf.currentFpsTime / RM_1000000; // Convert to milliseconds + + if (startCaptuerTime_ > 0) { + long long diff = + startCaptuerTime_ > nowTime ? (LLONG_MAX - startCaptuerTime_ + nowTime) : (nowTime - startCaptuerTime_); + + if (diff > RM_5000 && (!CheckCounterId())) { + startCaptuerTime_ = RM_0; + } + } + + if (fps_ > fcf.fps || frameTime_ < curframeTime) { + if (startCaptuerTime_ == 0) { + startCaptuerTime_ = nowTime; + ThreadGetHiperf(startCaptuerTime_); + } + } + templateMap["fpsWarn"] = std::to_string(fcf.fps); + templateMap["FrameTimeWarn"] = std::to_string(fcf.currentFpsTime); + templateMap["TraceTime"] = std::to_string(startCaptuerTime_); + LOGI("Effective:ItemData map size(%u)", templateMap.size()); + return templateMap; +} + +bool Effective::CheckCounterId() +{ + std::string result; + std::string hiprofilerCmd = CMD_COMMAND_MAP.at(CmdCommand::HIPROFILER_CMD); + LOGD("Loading hiprofiler command"); + SPUtils::LoadCmd(hiprofilerCmd, result); + if (result.empty()) { + LOGW("Failed to load hiprofiler command or received empty result."); + return false; + } + + if (result.find("-k") != std::string::npos) { + LOGD("Command contains '-k'."); + return true; + } + + LOGD("Command does not contain '-k'."); + return false; +} +std::thread Effective::ThreadGetHiperf(long long timeStamp) +{ + auto thGetTrace = [this, timeStamp]() { this->GetHiperf(std::to_string(timeStamp)); }; + std::thread spThread(thGetTrace); + spThread.detach(); + return spThread; +} + +void Effective::GetHiperf(const std::string &traceName) +{ + std::string result; + std::string tmp = SetHiperf(traceName); + std::cout << tmp << std::endl; + SPUtils::LoadCmd(tmp, result); + LOGD("hiprofiler exec (%s), hiprofiler exec trace name(%s), hiprofiler exec end (%s)", + tmp.c_str(), traceName.c_str(), result.c_str()); +} + +std::string Effective::SetHiperf(const std::string &traceName) +{ + std::string hiPrefix = "hiprofiler_"; + std::string dataPrefix = "perf_"; + requestId_++; + std::string trtmp = strOne_ + hiPrefix + traceName + strTwo_ + "\n" + strThree_ + std::to_string(requestId_) + + "\n" + strFour_ + "\n" + strFive_ + hiPrefix + traceName + strSix_ + "\n" + strNine_ + strEleven_ + "\n" + + strSeven_ + dataPrefix + traceName + strEight_ + strTen_ + "\n" + conFig_; + return trtmp; +} +} +} \ No newline at end of file