148f512ceSopenharmony_ci/* 248f512ceSopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 448f512ceSopenharmony_ci * you may not use this file except in compliance with the License. 548f512ceSopenharmony_ci * You may obtain a copy of the License at 648f512ceSopenharmony_ci * 748f512ceSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 848f512ceSopenharmony_ci * 948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and 1348f512ceSopenharmony_ci * limitations under the License. 1448f512ceSopenharmony_ci */ 1548f512ceSopenharmony_ci 1648f512ceSopenharmony_ci#define HILOG_TAG "Stat" 1748f512ceSopenharmony_ci 1848f512ceSopenharmony_ci#include "subcommand_stat.h" 1948f512ceSopenharmony_ci 2048f512ceSopenharmony_ci#include <csignal> 2148f512ceSopenharmony_ci#include <iostream> 2248f512ceSopenharmony_ci#include <memory> 2348f512ceSopenharmony_ci 2448f512ceSopenharmony_ci#include "debug_logger.h" 2548f512ceSopenharmony_ci#include "hiperf_hilog.h" 2648f512ceSopenharmony_ci#include "utilities.h" 2748f512ceSopenharmony_ci 2848f512ceSopenharmony_ciconst uint16_t ONE_HUNDRED = 100; 2948f512ceSopenharmony_ciconst uint16_t THOUSNADS_SEPARATOR = 3; 3048f512ceSopenharmony_cinamespace OHOS { 3148f512ceSopenharmony_cinamespace Developtools { 3248f512ceSopenharmony_cinamespace HiPerf { 3348f512ceSopenharmony_cistatic std::map<pid_t, ThreadInfos> thread_map_; 3448f512ceSopenharmony_cistatic bool g_reportCpuFlag = false; 3548f512ceSopenharmony_cistatic bool g_reportThreadFlag = false; 3648f512ceSopenharmony_cistatic VirtualRuntime g_runtimeInstance; 3748f512ceSopenharmony_civoid SubCommandStat::DumpOptions() const 3848f512ceSopenharmony_ci{ 3948f512ceSopenharmony_ci printf("DumpOptions:\n"); 4048f512ceSopenharmony_ci printf(" targetSystemWide:\t%s\n", targetSystemWide_ ? "true" : "false"); 4148f512ceSopenharmony_ci printf(" selectCpus:\t%s\n", VectorToString(selectCpus_).c_str()); 4248f512ceSopenharmony_ci printf(" timeStopSec:\t%f sec\n", timeStopSec_); 4348f512ceSopenharmony_ci printf(" timeReportMs:\t%d ms\n", timeReportMs_); 4448f512ceSopenharmony_ci printf(" selectEvents:\t%s\n", VectorToString(selectEvents_).c_str()); 4548f512ceSopenharmony_ci printf(" selectGroups:\t%s\n", VectorToString(selectGroups_).c_str()); 4648f512ceSopenharmony_ci printf(" noCreateNew:\t%s\n", noCreateNew_ ? "true" : "false"); 4748f512ceSopenharmony_ci printf(" appPackage:\t%s\n", appPackage_.c_str()); 4848f512ceSopenharmony_ci printf(" checkAppMs_:\t%d\n", checkAppMs_); 4948f512ceSopenharmony_ci printf(" selectPids:\t%s\n", VectorToString(selectPids_).c_str()); 5048f512ceSopenharmony_ci printf(" selectTids:\t%s\n", VectorToString(selectTids_).c_str()); 5148f512ceSopenharmony_ci printf(" restart:\t%s\n", restart_ ? "true" : "false"); 5248f512ceSopenharmony_ci printf(" perCore:\t%s\n", perCpus_ ? "true" : "false"); 5348f512ceSopenharmony_ci printf(" perTread:\t%s\n", perThreads_ ? "true" : "false"); 5448f512ceSopenharmony_ci printf(" verbose:\t%s\n", verboseReport_ ? "true" : "false"); 5548f512ceSopenharmony_ci} 5648f512ceSopenharmony_ci 5748f512ceSopenharmony_cibool SubCommandStat::ParseOption(std::vector<std::string> &args) 5848f512ceSopenharmony_ci{ 5948f512ceSopenharmony_ci if (args.size() == 1 and args[0] == "-h") { 6048f512ceSopenharmony_ci args.clear(); 6148f512ceSopenharmony_ci helpOption_ = true; 6248f512ceSopenharmony_ci PrintUsage(); 6348f512ceSopenharmony_ci return true; 6448f512ceSopenharmony_ci } 6548f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-a", targetSystemWide_)) { 6648f512ceSopenharmony_ci HLOGD("get option -a failed"); 6748f512ceSopenharmony_ci return false; 6848f512ceSopenharmony_ci } 6948f512ceSopenharmony_ci if (targetSystemWide_ && !IsSupportNonDebuggableApp()) { 7048f512ceSopenharmony_ci HLOGD("-a option needs root privilege for system wide profiling."); 7148f512ceSopenharmony_ci printf("-a option needs root privilege for system wide profiling.\n"); 7248f512ceSopenharmony_ci return false; 7348f512ceSopenharmony_ci } 7448f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-c", selectCpus_)) { 7548f512ceSopenharmony_ci HLOGD("get option -c failed"); 7648f512ceSopenharmony_ci return false; 7748f512ceSopenharmony_ci } 7848f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-d", timeStopSec_)) { 7948f512ceSopenharmony_ci HLOGD("get option -d failed"); 8048f512ceSopenharmony_ci return false; 8148f512ceSopenharmony_ci } 8248f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-i", timeReportMs_)) { 8348f512ceSopenharmony_ci HLOGD("get option -i failed"); 8448f512ceSopenharmony_ci return false; 8548f512ceSopenharmony_ci } 8648f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-e", selectEvents_)) { 8748f512ceSopenharmony_ci HLOGD("get option -e failed"); 8848f512ceSopenharmony_ci return false; 8948f512ceSopenharmony_ci } 9048f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-g", selectGroups_)) { 9148f512ceSopenharmony_ci HLOGD("get option -g failed"); 9248f512ceSopenharmony_ci return false; 9348f512ceSopenharmony_ci } 9448f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--no-inherit", noCreateNew_)) { 9548f512ceSopenharmony_ci HLOGD("get option --no-inherit failed"); 9648f512ceSopenharmony_ci return false; 9748f512ceSopenharmony_ci } 9848f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--app", appPackage_)) { 9948f512ceSopenharmony_ci HLOGD("get option --app failed"); 10048f512ceSopenharmony_ci return false; 10148f512ceSopenharmony_ci } 10248f512ceSopenharmony_ci if (!IsExistDebugByApp(appPackage_)) { 10348f512ceSopenharmony_ci return false; 10448f512ceSopenharmony_ci } 10548f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--chkms", checkAppMs_)) { 10648f512ceSopenharmony_ci return false; 10748f512ceSopenharmony_ci } 10848f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-p", selectPids_)) { 10948f512ceSopenharmony_ci HLOGD("get option -p failed"); 11048f512ceSopenharmony_ci return false; 11148f512ceSopenharmony_ci } 11248f512ceSopenharmony_ci if (!IsExistDebugByPid(selectPids_)) { 11348f512ceSopenharmony_ci return false; 11448f512ceSopenharmony_ci } 11548f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "-t", selectTids_)) { 11648f512ceSopenharmony_ci HLOGD("get option -t failed"); 11748f512ceSopenharmony_ci return false; 11848f512ceSopenharmony_ci } 11948f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--restart", restart_)) { 12048f512ceSopenharmony_ci HLOGD("get option --restart failed"); 12148f512ceSopenharmony_ci return false; 12248f512ceSopenharmony_ci } 12348f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--per-core", perCpus_)) { 12448f512ceSopenharmony_ci HLOGD("get option --per-core failed"); 12548f512ceSopenharmony_ci return false; 12648f512ceSopenharmony_ci } 12748f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--per-thread", perThreads_)) { 12848f512ceSopenharmony_ci HLOGD("get option --per-thread failed"); 12948f512ceSopenharmony_ci return false; 13048f512ceSopenharmony_ci } 13148f512ceSopenharmony_ci if (!Option::GetOptionValue(args, "--verbose", verboseReport_)) { 13248f512ceSopenharmony_ci HLOGD("get option --verbose failed"); 13348f512ceSopenharmony_ci return false; 13448f512ceSopenharmony_ci } 13548f512ceSopenharmony_ci return ParseSpecialOption(args); 13648f512ceSopenharmony_ci} 13748f512ceSopenharmony_ci 13848f512ceSopenharmony_cibool SubCommandStat::ParseSpecialOption(std::vector<std::string> &args) 13948f512ceSopenharmony_ci{ 14048f512ceSopenharmony_ci if (!Option::GetOptionTrackedCommand(args, trackedCommand_)) { 14148f512ceSopenharmony_ci HLOGD("get cmd failed"); 14248f512ceSopenharmony_ci return false; 14348f512ceSopenharmony_ci } 14448f512ceSopenharmony_ci if (!args.empty()) { 14548f512ceSopenharmony_ci HLOGD("redundant option(s)"); 14648f512ceSopenharmony_ci return false; 14748f512ceSopenharmony_ci } 14848f512ceSopenharmony_ci return true; 14948f512ceSopenharmony_ci} 15048f512ceSopenharmony_ci 15148f512ceSopenharmony_civoid SubCommandStat::PrintUsage() 15248f512ceSopenharmony_ci{ 15348f512ceSopenharmony_ci printf("%s\n", Help().c_str()); 15448f512ceSopenharmony_ci} 15548f512ceSopenharmony_ci 15648f512ceSopenharmony_civoid SubCommandStat::SetReportFlags(bool cpuFlag, bool threadFlag) 15748f512ceSopenharmony_ci{ 15848f512ceSopenharmony_ci g_reportCpuFlag = cpuFlag; 15948f512ceSopenharmony_ci g_reportThreadFlag = threadFlag; 16048f512ceSopenharmony_ci} 16148f512ceSopenharmony_ci 16248f512ceSopenharmony_civoid SubCommandStat::Report(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents) 16348f512ceSopenharmony_ci{ 16448f512ceSopenharmony_ci bool isNeedPerCpuTid = false; 16548f512ceSopenharmony_ci for (auto it = countEvents.begin(); it != countEvents.end(); ++it) { 16648f512ceSopenharmony_ci if (!(it->second->summaries.empty())) { 16748f512ceSopenharmony_ci isNeedPerCpuTid = true; 16848f512ceSopenharmony_ci break; 16948f512ceSopenharmony_ci } 17048f512ceSopenharmony_ci } 17148f512ceSopenharmony_ci if (isNeedPerCpuTid) { 17248f512ceSopenharmony_ci PrintPerHead(); 17348f512ceSopenharmony_ci ReportDetailInfos(countEvents); 17448f512ceSopenharmony_ci } else { 17548f512ceSopenharmony_ci ReportNormal(countEvents); 17648f512ceSopenharmony_ci } 17748f512ceSopenharmony_ci} 17848f512ceSopenharmony_ci 17948f512ceSopenharmony_civoid SubCommandStat::PrintPerHead() 18048f512ceSopenharmony_ci{ 18148f512ceSopenharmony_ci // print head 18248f512ceSopenharmony_ci if (g_reportCpuFlag && g_reportThreadFlag) { 18348f512ceSopenharmony_ci printf(" %24s %-30s | %-30s %10s %10s %10s | %-32s | %s\n", "count", "event_name", "thread_name", 18448f512ceSopenharmony_ci "pid", "tid", "coreid", "comment", "coverage"); 18548f512ceSopenharmony_ci return; 18648f512ceSopenharmony_ci } 18748f512ceSopenharmony_ci if (g_reportCpuFlag) { 18848f512ceSopenharmony_ci printf(" %24s %-30s | %10s | %-32s | %s\n", "count", "event_name", "coreid", "comment", "coverage"); 18948f512ceSopenharmony_ci return; 19048f512ceSopenharmony_ci } 19148f512ceSopenharmony_ci printf(" %24s %-30s | %-30s %10s %10s | %-32s | %s\n", "count", "event_name", "thread_name", "pid", "tid", 19248f512ceSopenharmony_ci "comment", "coverage"); 19348f512ceSopenharmony_ci return; 19448f512ceSopenharmony_ci} 19548f512ceSopenharmony_ci 19648f512ceSopenharmony_civoid SubCommandStat::PrintPerValue(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, const float &ratio, 19748f512ceSopenharmony_ci std::string &configName) 19848f512ceSopenharmony_ci{ 19948f512ceSopenharmony_ci if (reportSum == nullptr) { 20048f512ceSopenharmony_ci return; 20148f512ceSopenharmony_ci } 20248f512ceSopenharmony_ci // print value 20348f512ceSopenharmony_ci std::string strEventCount = std::to_string(reportSum->eventCountSum); 20448f512ceSopenharmony_ci for (size_t i = strEventCount.size() >= 1 ? strEventCount.size() - 1 : 0, j = 1; i > 0; --i, ++j) { 20548f512ceSopenharmony_ci if (j == THOUSNADS_SEPARATOR) { 20648f512ceSopenharmony_ci j = 0; 20748f512ceSopenharmony_ci strEventCount.insert(strEventCount.begin() + i, ','); 20848f512ceSopenharmony_ci } 20948f512ceSopenharmony_ci } 21048f512ceSopenharmony_ci 21148f512ceSopenharmony_ci std::string commentStr; 21248f512ceSopenharmony_ci MakeComments(reportSum, commentStr); 21348f512ceSopenharmony_ci 21448f512ceSopenharmony_ci if (g_reportCpuFlag && g_reportThreadFlag) { 21548f512ceSopenharmony_ci printf(" %24s %-30s | %-30s %10d %10d %10d | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(), 21648f512ceSopenharmony_ci reportSum->threadName.c_str(), reportSum->pid, reportSum->tid, reportSum->cpu, commentStr.c_str(), 21748f512ceSopenharmony_ci reportSum->scaleSum * ratio); 21848f512ceSopenharmony_ci } else if (g_reportCpuFlag) { 21948f512ceSopenharmony_ci printf(" %24s %-30s | %10d | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(), 22048f512ceSopenharmony_ci reportSum->cpu, commentStr.c_str(), reportSum->scaleSum * ratio); 22148f512ceSopenharmony_ci } else { 22248f512ceSopenharmony_ci printf(" %24s %-30s | %-30s %10d %10d | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(), 22348f512ceSopenharmony_ci reportSum->threadName.c_str(), reportSum->pid, reportSum->tid, commentStr.c_str(), 22448f512ceSopenharmony_ci reportSum->scaleSum * ratio); 22548f512ceSopenharmony_ci } 22648f512ceSopenharmony_ci fflush(stdout); 22748f512ceSopenharmony_ci} 22848f512ceSopenharmony_ci 22948f512ceSopenharmony_civoid SubCommandStat::InitPerMap(const std::unique_ptr<PerfEvents::ReportSum> &newPerMap, 23048f512ceSopenharmony_ci const PerfEvents::Summary &summary, VirtualRuntime& virtualInstance) 23148f512ceSopenharmony_ci{ 23248f512ceSopenharmony_ci CHECK_TRUE(newPerMap == nullptr, NO_RETVAL, 0, ""); 23348f512ceSopenharmony_ci newPerMap->cpu = summary.cpu; 23448f512ceSopenharmony_ci if (g_reportCpuFlag && !g_reportThreadFlag) { 23548f512ceSopenharmony_ci return; 23648f512ceSopenharmony_ci } 23748f512ceSopenharmony_ci newPerMap->tid = summary.tid; 23848f512ceSopenharmony_ci newPerMap->pid = thread_map_.find(summary.tid)->second.pid; 23948f512ceSopenharmony_ci bool isTid = true; 24048f512ceSopenharmony_ci if (newPerMap->pid == newPerMap->tid) { 24148f512ceSopenharmony_ci isTid = false; 24248f512ceSopenharmony_ci } 24348f512ceSopenharmony_ci newPerMap->threadName = virtualInstance.ReadThreadName(summary.tid, isTid); 24448f512ceSopenharmony_ci} 24548f512ceSopenharmony_ci 24648f512ceSopenharmony_civoid SubCommandStat::GetPerKey(std::string &perKey, const PerfEvents::Summary &summary) 24748f512ceSopenharmony_ci{ 24848f512ceSopenharmony_ci perKey = ""; 24948f512ceSopenharmony_ci if (g_reportCpuFlag) { 25048f512ceSopenharmony_ci perKey += std::to_string(summary.cpu); 25148f512ceSopenharmony_ci perKey += "|"; 25248f512ceSopenharmony_ci } 25348f512ceSopenharmony_ci if (g_reportThreadFlag) { 25448f512ceSopenharmony_ci perKey += std::to_string(summary.tid); 25548f512ceSopenharmony_ci } 25648f512ceSopenharmony_ci return; 25748f512ceSopenharmony_ci} 25848f512ceSopenharmony_ci 25948f512ceSopenharmony_civoid SubCommandStat::ReportDetailInfos( 26048f512ceSopenharmony_ci const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents) 26148f512ceSopenharmony_ci{ 26248f512ceSopenharmony_ci std::string perKey = ""; 26348f512ceSopenharmony_ci std::map<std::string, std::unique_ptr<PerfEvents::ReportSum>> perMaps; 26448f512ceSopenharmony_ci for (auto event = countEvents.begin(); event != countEvents.end(); ++event) { 26548f512ceSopenharmony_ci if (event->second == nullptr || event->second->eventCount == 0) { 26648f512ceSopenharmony_ci continue; 26748f512ceSopenharmony_ci } 26848f512ceSopenharmony_ci constexpr float ratio {100.0}; 26948f512ceSopenharmony_ci std::string configName = event->first; 27048f512ceSopenharmony_ci perMaps.clear(); 27148f512ceSopenharmony_ci for (auto &it : event->second->summaries) { 27248f512ceSopenharmony_ci GetPerKey(perKey, it); 27348f512ceSopenharmony_ci if (perMaps.count(perKey) == 0) { 27448f512ceSopenharmony_ci auto perMap = std::make_unique<PerfEvents::ReportSum>(PerfEvents::ReportSum {}); 27548f512ceSopenharmony_ci InitPerMap(perMap, it, g_runtimeInstance); 27648f512ceSopenharmony_ci perMaps[perKey] = std::move(perMap); 27748f512ceSopenharmony_ci } 27848f512ceSopenharmony_ci if (perMaps[perKey] == nullptr) { 27948f512ceSopenharmony_ci continue; 28048f512ceSopenharmony_ci } 28148f512ceSopenharmony_ci perMaps[perKey]->configName = GetDetailComments(event->second, perMaps[perKey]->commentSum, 28248f512ceSopenharmony_ci it, configName); 28348f512ceSopenharmony_ci perMaps[perKey]->eventCountSum += it.eventCount; 28448f512ceSopenharmony_ci if (it.timeRunning < it.timeEnabled && it.timeRunning != 0) { 28548f512ceSopenharmony_ci perMaps[perKey]->scaleSum = 1 / (static_cast<double>(it.timeEnabled) / it.timeRunning); 28648f512ceSopenharmony_ci } 28748f512ceSopenharmony_ci } 28848f512ceSopenharmony_ci for (auto iper = perMaps.begin(); iper != perMaps.end(); iper++) { 28948f512ceSopenharmony_ci PrintPerValue(iper->second, ratio, configName); 29048f512ceSopenharmony_ci } 29148f512ceSopenharmony_ci } 29248f512ceSopenharmony_ci} 29348f512ceSopenharmony_ci 29448f512ceSopenharmony_civoid SubCommandStat::ReportNormal( 29548f512ceSopenharmony_ci const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents) 29648f512ceSopenharmony_ci{ 29748f512ceSopenharmony_ci // print head 29848f512ceSopenharmony_ci printf(" %24s %-30s | %-32s | %s\n", "count", "name", "comment", "coverage"); 29948f512ceSopenharmony_ci std::map<std::string, std::string> comments; 30048f512ceSopenharmony_ci GetComments(countEvents, comments); 30148f512ceSopenharmony_ci for (auto it = countEvents.begin(); it != countEvents.end(); ++it) { 30248f512ceSopenharmony_ci double scale = 1.0; 30348f512ceSopenharmony_ci constexpr float ratio {100.0}; 30448f512ceSopenharmony_ci std::string configName = it->first; 30548f512ceSopenharmony_ci std::string comment = comments[configName]; 30648f512ceSopenharmony_ci std::string strEventCount = std::to_string(it->second->eventCount); 30748f512ceSopenharmony_ci for (size_t i = strEventCount.size() >= 1 ? strEventCount.size() - 1 : 0, j = 1; i > 0; --i, ++j) { 30848f512ceSopenharmony_ci if (j == THOUSNADS_SEPARATOR) { 30948f512ceSopenharmony_ci strEventCount.insert(strEventCount.begin() + i, ','); 31048f512ceSopenharmony_ci j = 0; 31148f512ceSopenharmony_ci } 31248f512ceSopenharmony_ci } 31348f512ceSopenharmony_ci if (it->second->timeRunning < it->second->timeEnabled && it->second->timeRunning != 0) { 31448f512ceSopenharmony_ci scale = 1 / (static_cast<double>(it->second->timeEnabled) / it->second->timeRunning); 31548f512ceSopenharmony_ci } 31648f512ceSopenharmony_ci printf(" %24s %-30s | %-32s | (%.0lf%%)\n", strEventCount.c_str(), configName.c_str(), 31748f512ceSopenharmony_ci comment.c_str(), scale * ratio); 31848f512ceSopenharmony_ci 31948f512ceSopenharmony_ci fflush(stdout); 32048f512ceSopenharmony_ci } 32148f512ceSopenharmony_ci} 32248f512ceSopenharmony_ci 32348f512ceSopenharmony_cibool SubCommandStat::FindEventCount(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents, 32448f512ceSopenharmony_ci const std::string &configName, const __u64 group_id, __u64 &eventCount, double &scale) 32548f512ceSopenharmony_ci{ 32648f512ceSopenharmony_ci auto itr = countEvents.find(configName); 32748f512ceSopenharmony_ci if (itr != countEvents.end()) { 32848f512ceSopenharmony_ci eventCount = itr->second->eventCount; 32948f512ceSopenharmony_ci if (itr->second->id == group_id 33048f512ceSopenharmony_ci && itr->second->timeRunning < itr->second->timeEnabled 33148f512ceSopenharmony_ci && itr->second->timeRunning != 0) { 33248f512ceSopenharmony_ci scale = static_cast<double>(itr->second->timeEnabled) / itr->second->timeRunning; 33348f512ceSopenharmony_ci return true; 33448f512ceSopenharmony_ci } 33548f512ceSopenharmony_ci } 33648f512ceSopenharmony_ci return false; 33748f512ceSopenharmony_ci} 33848f512ceSopenharmony_ci 33948f512ceSopenharmony_cibool SubCommandStat::FindPerCoreEventCount(PerfEvents::Summary &summary, __u64 &eventCount, double &scale) 34048f512ceSopenharmony_ci{ 34148f512ceSopenharmony_ci eventCount = summary.eventCount; 34248f512ceSopenharmony_ci if (summary.timeRunning < summary.timeEnabled && summary.timeRunning != 0) { 34348f512ceSopenharmony_ci scale = static_cast<double>(summary.timeEnabled) / summary.timeRunning; 34448f512ceSopenharmony_ci return true; 34548f512ceSopenharmony_ci } 34648f512ceSopenharmony_ci return false; 34748f512ceSopenharmony_ci} 34848f512ceSopenharmony_ci 34948f512ceSopenharmony_cistd::string SubCommandStat::GetCommentConfigName( 35048f512ceSopenharmony_ci const std::unique_ptr<PerfEvents::CountEvent> &countEvent, std::string eventName) 35148f512ceSopenharmony_ci{ 35248f512ceSopenharmony_ci std::string commentConfigName = ""; 35348f512ceSopenharmony_ci CHECK_TRUE(countEvent == nullptr || eventName.length() == 0, commentConfigName, 0, ""); 35448f512ceSopenharmony_ci if (countEvent->userOnly) { 35548f512ceSopenharmony_ci commentConfigName = eventName + ":u"; 35648f512ceSopenharmony_ci } else if (countEvent->kernelOnly) { 35748f512ceSopenharmony_ci commentConfigName = eventName + ":k"; 35848f512ceSopenharmony_ci } else { 35948f512ceSopenharmony_ci commentConfigName = eventName; 36048f512ceSopenharmony_ci } 36148f512ceSopenharmony_ci return commentConfigName; 36248f512ceSopenharmony_ci} 36348f512ceSopenharmony_ci 36448f512ceSopenharmony_civoid SubCommandStat::MakeComments(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, std::string &commentStr) 36548f512ceSopenharmony_ci{ 36648f512ceSopenharmony_ci CHECK_TRUE(reportSum == nullptr || reportSum->commentSum == 0, NO_RETVAL, 0, ""); 36748f512ceSopenharmony_ci if (reportSum->configName == "sw-task-clock") { 36848f512ceSopenharmony_ci commentStr = StringPrintf("%lf cpus used", reportSum->commentSum); 36948f512ceSopenharmony_ci return; 37048f512ceSopenharmony_ci } 37148f512ceSopenharmony_ci if (reportSum->configName == "hw-cpu-cycles") { 37248f512ceSopenharmony_ci commentStr = StringPrintf("%lf GHz", reportSum->commentSum); 37348f512ceSopenharmony_ci return; 37448f512ceSopenharmony_ci } 37548f512ceSopenharmony_ci if (reportSum->configName == "hw-instructions") { 37648f512ceSopenharmony_ci commentStr = StringPrintf("%lf cycles per instruction", reportSum->commentSum); 37748f512ceSopenharmony_ci return; 37848f512ceSopenharmony_ci } 37948f512ceSopenharmony_ci if (reportSum->configName == "hw-branch-misses") { 38048f512ceSopenharmony_ci commentStr = StringPrintf("%lf miss rate", reportSum->commentSum); 38148f512ceSopenharmony_ci return; 38248f512ceSopenharmony_ci } 38348f512ceSopenharmony_ci 38448f512ceSopenharmony_ci if (reportSum->commentSum > 1e9) { 38548f512ceSopenharmony_ci commentStr = StringPrintf("%.3lf G/sec", reportSum->commentSum / 1e9); 38648f512ceSopenharmony_ci return; 38748f512ceSopenharmony_ci } 38848f512ceSopenharmony_ci if (reportSum->commentSum > 1e6) { 38948f512ceSopenharmony_ci commentStr = StringPrintf("%.3lf M/sec", reportSum->commentSum / 1e6); 39048f512ceSopenharmony_ci return; 39148f512ceSopenharmony_ci } 39248f512ceSopenharmony_ci if (reportSum->commentSum > 1e3) { 39348f512ceSopenharmony_ci commentStr = StringPrintf("%.3lf K/sec", reportSum->commentSum / 1e3); 39448f512ceSopenharmony_ci return; 39548f512ceSopenharmony_ci } 39648f512ceSopenharmony_ci commentStr = StringPrintf("%.3lf /sec", reportSum->commentSum); 39748f512ceSopenharmony_ci} 39848f512ceSopenharmony_ci 39948f512ceSopenharmony_cistd::string SubCommandStat::GetDetailComments(const std::unique_ptr<PerfEvents::CountEvent> &countEvent, 40048f512ceSopenharmony_ci double &comment, PerfEvents::Summary &summary, std::string &configName) 40148f512ceSopenharmony_ci{ 40248f512ceSopenharmony_ci double running_time_in_sec = 0; 40348f512ceSopenharmony_ci double main_scale = 1.0; 40448f512ceSopenharmony_ci bool findRunningTime = FindPercoreRunningTime(summary, running_time_in_sec, main_scale); 40548f512ceSopenharmony_ci if (configName == GetCommentConfigName(countEvent, "sw-cpu-clock")) { 40648f512ceSopenharmony_ci comment = 0; 40748f512ceSopenharmony_ci return "sw-cpu-clock"; 40848f512ceSopenharmony_ci } 40948f512ceSopenharmony_ci double scale = 1.0; 41048f512ceSopenharmony_ci if (summary.timeRunning < summary.timeEnabled && summary.timeRunning != 0) { 41148f512ceSopenharmony_ci scale = static_cast<double>(summary.timeEnabled) / summary.timeRunning; 41248f512ceSopenharmony_ci } 41348f512ceSopenharmony_ci if (configName == GetCommentConfigName(countEvent, "sw-task-clock")) { 41448f512ceSopenharmony_ci comment += countEvent->usedCpus * scale; 41548f512ceSopenharmony_ci return "sw-task-clock"; 41648f512ceSopenharmony_ci } 41748f512ceSopenharmony_ci if (configName == GetCommentConfigName(countEvent, "hw-cpu-cycles")) { 41848f512ceSopenharmony_ci if (findRunningTime) { 41948f512ceSopenharmony_ci double hz = 0; 42048f512ceSopenharmony_ci if (abs(running_time_in_sec) > ALMOST_ZERO) { 42148f512ceSopenharmony_ci hz = summary.eventCount / (running_time_in_sec / scale); 42248f512ceSopenharmony_ci } 42348f512ceSopenharmony_ci comment += hz / 1e9; 42448f512ceSopenharmony_ci } else { 42548f512ceSopenharmony_ci comment += 0; 42648f512ceSopenharmony_ci } 42748f512ceSopenharmony_ci return "hw-cpu-cycles"; 42848f512ceSopenharmony_ci } 42948f512ceSopenharmony_ci if (configName == GetCommentConfigName(countEvent, "hw-instructions") && summary.eventCount != 0) { 43048f512ceSopenharmony_ci double otherScale = 1.0; 43148f512ceSopenharmony_ci __u64 cpuCyclesCount = 0; 43248f512ceSopenharmony_ci bool other = FindPerCoreEventCount(summary, cpuCyclesCount, otherScale); 43348f512ceSopenharmony_ci if (other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) { 43448f512ceSopenharmony_ci comment += static_cast<double>(cpuCyclesCount) / summary.eventCount; 43548f512ceSopenharmony_ci return "hw-instructions"; 43648f512ceSopenharmony_ci } 43748f512ceSopenharmony_ci } 43848f512ceSopenharmony_ci if (configName == GetCommentConfigName(countEvent, "hw-branch-misses")) { 43948f512ceSopenharmony_ci double otherScale = 1.0; 44048f512ceSopenharmony_ci __u64 branchInstructionsCount = 0; 44148f512ceSopenharmony_ci bool other = FindPerCoreEventCount(summary, branchInstructionsCount, otherScale); 44248f512ceSopenharmony_ci if ((other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) && 44348f512ceSopenharmony_ci branchInstructionsCount != 0) { 44448f512ceSopenharmony_ci comment += (static_cast<double>(summary.eventCount) / branchInstructionsCount) * ONE_HUNDRED; 44548f512ceSopenharmony_ci return "hw-branch-misses"; 44648f512ceSopenharmony_ci } 44748f512ceSopenharmony_ci } 44848f512ceSopenharmony_ci return HandleOtherConfig(comment, summary, running_time_in_sec, scale, findRunningTime); 44948f512ceSopenharmony_ci} 45048f512ceSopenharmony_ci 45148f512ceSopenharmony_cistd::string SubCommandStat::HandleOtherConfig(double &comment, PerfEvents::Summary &summary, double running_time_in_sec, 45248f512ceSopenharmony_ci double scale, bool findRunningTime) 45348f512ceSopenharmony_ci{ 45448f512ceSopenharmony_ci comment = 0; 45548f512ceSopenharmony_ci if (findRunningTime) { 45648f512ceSopenharmony_ci double rate = 0; 45748f512ceSopenharmony_ci if (scale != 0) { 45848f512ceSopenharmony_ci rate = summary.eventCount / (running_time_in_sec / scale); 45948f512ceSopenharmony_ci } 46048f512ceSopenharmony_ci comment += rate; 46148f512ceSopenharmony_ci } 46248f512ceSopenharmony_ci return ""; 46348f512ceSopenharmony_ci} 46448f512ceSopenharmony_ci 46548f512ceSopenharmony_cibool SubCommandStat::IsMonitoredAtAllTime(const double &scale) 46648f512ceSopenharmony_ci{ 46748f512ceSopenharmony_ci constexpr double SCALE_ERROR_LIMIT = 1e-5; 46848f512ceSopenharmony_ci return (fabs(scale - 1.0) < SCALE_ERROR_LIMIT); 46948f512ceSopenharmony_ci} 47048f512ceSopenharmony_ci 47148f512ceSopenharmony_civoid SubCommandStat::GetComments(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents, 47248f512ceSopenharmony_ci std::map<std::string, std::string> &comments) 47348f512ceSopenharmony_ci{ 47448f512ceSopenharmony_ci double running_time_in_sec = 0; 47548f512ceSopenharmony_ci __u64 group_id = 0; 47648f512ceSopenharmony_ci double main_scale = 1.0; 47748f512ceSopenharmony_ci bool findRunningTime = FindRunningTime(countEvents, running_time_in_sec, group_id, main_scale); 47848f512ceSopenharmony_ci for (auto it = countEvents.begin(); it != countEvents.end(); it++) { 47948f512ceSopenharmony_ci std::string configName = it->first; 48048f512ceSopenharmony_ci std::string commentConfigName = GetCommentConfigName(it->second, "sw-cpu-clock"); 48148f512ceSopenharmony_ci if (configName == commentConfigName) { 48248f512ceSopenharmony_ci comments[configName] = ""; 48348f512ceSopenharmony_ci continue; 48448f512ceSopenharmony_ci } 48548f512ceSopenharmony_ci double scale = 1.0; 48648f512ceSopenharmony_ci if (it->second->timeRunning < it->second->timeEnabled && it->second->timeRunning != 0) { 48748f512ceSopenharmony_ci scale = static_cast<double>(it->second->timeEnabled) / it->second->timeRunning; 48848f512ceSopenharmony_ci } 48948f512ceSopenharmony_ci commentConfigName = GetCommentConfigName(it->second, "sw-task-clock"); 49048f512ceSopenharmony_ci if (configName == commentConfigName) { 49148f512ceSopenharmony_ci double usedCpus = it->second->usedCpus * scale; 49248f512ceSopenharmony_ci comments[configName] = StringPrintf("%lf cpus used", usedCpus); 49348f512ceSopenharmony_ci continue; 49448f512ceSopenharmony_ci } 49548f512ceSopenharmony_ci commentConfigName = GetCommentConfigName(it->second, "hw-cpu-cycles"); 49648f512ceSopenharmony_ci if (configName == commentConfigName) { 49748f512ceSopenharmony_ci if (findRunningTime && 49848f512ceSopenharmony_ci ((group_id == it->second->id) || 49948f512ceSopenharmony_ci (IsMonitoredAtAllTime(main_scale) && IsMonitoredAtAllTime(scale)))) { 50048f512ceSopenharmony_ci double hz = 0; 50148f512ceSopenharmony_ci if (abs(running_time_in_sec) > ALMOST_ZERO) { 50248f512ceSopenharmony_ci hz = it->second->eventCount / (running_time_in_sec / scale); 50348f512ceSopenharmony_ci } 50448f512ceSopenharmony_ci comments[configName] = StringPrintf("%lf GHz", hz / 1e9); 50548f512ceSopenharmony_ci } else { 50648f512ceSopenharmony_ci comments[configName] = ""; 50748f512ceSopenharmony_ci } 50848f512ceSopenharmony_ci continue; 50948f512ceSopenharmony_ci } 51048f512ceSopenharmony_ci commentConfigName = GetCommentConfigName(it->second, "hw-instructions"); 51148f512ceSopenharmony_ci if (configName == commentConfigName && it->second->eventCount != 0) { 51248f512ceSopenharmony_ci std::string cpuSyclesName = GetCommentConfigName(it->second, "hw-cpu-cycles"); 51348f512ceSopenharmony_ci double otherScale = 1.0; 51448f512ceSopenharmony_ci __u64 cpuCyclesCount = 0; 51548f512ceSopenharmony_ci bool other = FindEventCount(countEvents, cpuSyclesName, it->second->id, cpuCyclesCount, 51648f512ceSopenharmony_ci otherScale); 51748f512ceSopenharmony_ci if (other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) { 51848f512ceSopenharmony_ci double cpi = static_cast<double>(cpuCyclesCount) / it->second->eventCount; 51948f512ceSopenharmony_ci comments[configName] = StringPrintf("%lf cycles per instruction", cpi); 52048f512ceSopenharmony_ci continue; 52148f512ceSopenharmony_ci } 52248f512ceSopenharmony_ci } 52348f512ceSopenharmony_ci commentConfigName = GetCommentConfigName(it->second, "hw-branch-misses"); 52448f512ceSopenharmony_ci if (configName == commentConfigName) { 52548f512ceSopenharmony_ci std::string branchInsName = GetCommentConfigName(it->second, "hw-branch-instructions"); 52648f512ceSopenharmony_ci double otherScale = 1.0; 52748f512ceSopenharmony_ci __u64 branchInstructionsCount = 0; 52848f512ceSopenharmony_ci bool other = FindEventCount(countEvents, branchInsName, it->second->id, 52948f512ceSopenharmony_ci branchInstructionsCount, otherScale); 53048f512ceSopenharmony_ci if ((other || (IsMonitoredAtAllTime(otherScale) && IsMonitoredAtAllTime(scale))) && 53148f512ceSopenharmony_ci branchInstructionsCount != 0) { 53248f512ceSopenharmony_ci double miss_rate = 53348f512ceSopenharmony_ci static_cast<double>(it->second->eventCount) / branchInstructionsCount; 53448f512ceSopenharmony_ci comments[configName] = StringPrintf("%lf miss rate", miss_rate * ONE_HUNDRED); 53548f512ceSopenharmony_ci continue; 53648f512ceSopenharmony_ci } 53748f512ceSopenharmony_ci } 53848f512ceSopenharmony_ci if (findRunningTime && ((group_id == it->second->id) || (IsMonitoredAtAllTime(main_scale) && 53948f512ceSopenharmony_ci IsMonitoredAtAllTime(scale)))) { 54048f512ceSopenharmony_ci double rate = it->second->eventCount / (running_time_in_sec / scale); 54148f512ceSopenharmony_ci if (rate > 1e9) { 54248f512ceSopenharmony_ci comments[configName] = StringPrintf("%.3lf G/sec", rate / 1e9); 54348f512ceSopenharmony_ci continue; 54448f512ceSopenharmony_ci } 54548f512ceSopenharmony_ci if (rate > 1e6) { 54648f512ceSopenharmony_ci comments[configName] = StringPrintf("%.3lf M/sec", rate / 1e6); 54748f512ceSopenharmony_ci continue; 54848f512ceSopenharmony_ci } 54948f512ceSopenharmony_ci if (rate > 1e3) { 55048f512ceSopenharmony_ci comments[configName] = StringPrintf("%.3lf K/sec", rate / 1e3); 55148f512ceSopenharmony_ci continue; 55248f512ceSopenharmony_ci } 55348f512ceSopenharmony_ci comments[configName] = StringPrintf("%.3lf /sec", rate); 55448f512ceSopenharmony_ci } else { 55548f512ceSopenharmony_ci comments[configName] = ""; 55648f512ceSopenharmony_ci } 55748f512ceSopenharmony_ci } 55848f512ceSopenharmony_ci} 55948f512ceSopenharmony_ci 56048f512ceSopenharmony_cibool SubCommandStat::FindRunningTime( 56148f512ceSopenharmony_ci const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents, 56248f512ceSopenharmony_ci double &running_time_in_sec, __u64 &group_id, double &main_scale) 56348f512ceSopenharmony_ci{ 56448f512ceSopenharmony_ci for (auto it = countEvents.begin(); it != countEvents.end(); it++) { 56548f512ceSopenharmony_ci if ((it->first == "sw-task-clock" || it->first == "sw-task-clock:u" || 56648f512ceSopenharmony_ci it->first == "sw-task-clock:k" || it->first == "sw-cpu-clock" || 56748f512ceSopenharmony_ci it->first == "sw-cpu-clock:u" || it->first == "sw-cpu-clock:k") && 56848f512ceSopenharmony_ci it->second->eventCount != 0u) { 56948f512ceSopenharmony_ci group_id = it->second->id; 57048f512ceSopenharmony_ci running_time_in_sec = it->second->eventCount / 1e9; 57148f512ceSopenharmony_ci if (it->second->timeRunning < it->second->timeEnabled && 57248f512ceSopenharmony_ci it->second->timeRunning != 0) { 57348f512ceSopenharmony_ci main_scale = 57448f512ceSopenharmony_ci static_cast<double>(it->second->timeEnabled) / it->second->timeRunning; 57548f512ceSopenharmony_ci } 57648f512ceSopenharmony_ci return true; 57748f512ceSopenharmony_ci } 57848f512ceSopenharmony_ci } 57948f512ceSopenharmony_ci return false; 58048f512ceSopenharmony_ci} 58148f512ceSopenharmony_ci 58248f512ceSopenharmony_cibool SubCommandStat::FindPercoreRunningTime(PerfEvents::Summary &summary, double &running_time_int_sec, 58348f512ceSopenharmony_ci double &main_scale) 58448f512ceSopenharmony_ci{ 58548f512ceSopenharmony_ci CHECK_TRUE(summary.eventCount == 0, false, 0, ""); 58648f512ceSopenharmony_ci running_time_int_sec = summary.eventCount / 1e9; 58748f512ceSopenharmony_ci if (summary.timeRunning < summary.timeEnabled && summary.timeRunning != 0) { 58848f512ceSopenharmony_ci main_scale = static_cast<double>(summary.timeEnabled) / summary.timeRunning; 58948f512ceSopenharmony_ci } 59048f512ceSopenharmony_ci return true; 59148f512ceSopenharmony_ci} 59248f512ceSopenharmony_ci 59348f512ceSopenharmony_cibool SubCommandStat::CheckOptionPidAndApp(std::vector<pid_t> pids) 59448f512ceSopenharmony_ci{ 59548f512ceSopenharmony_ci if (!CheckOptionPid(pids)) { 59648f512ceSopenharmony_ci printf("Problems finding threads of monitor\n\n"); 59748f512ceSopenharmony_ci printf("Usage: perf stat [<options>] [<command>]\n\n"); 59848f512ceSopenharmony_ci printf("-p <pid> stat events on existing process id\n"); 59948f512ceSopenharmony_ci printf("-t <tid> stat events on existing thread id\n"); 60048f512ceSopenharmony_ci return false; 60148f512ceSopenharmony_ci } 60248f512ceSopenharmony_ci return true; 60348f512ceSopenharmony_ci} 60448f512ceSopenharmony_ci 60548f512ceSopenharmony_cibool SubCommandStat::CheckOptionPid(std::vector<pid_t> pids) 60648f512ceSopenharmony_ci{ 60748f512ceSopenharmony_ci if (pids.empty()) { 60848f512ceSopenharmony_ci return true; 60948f512ceSopenharmony_ci } 61048f512ceSopenharmony_ci 61148f512ceSopenharmony_ci for (auto pid : pids) { 61248f512ceSopenharmony_ci if (!IsDir("/proc/" + std::to_string(pid))) { 61348f512ceSopenharmony_ci printf("not exit pid %d\n", pid); 61448f512ceSopenharmony_ci return false; 61548f512ceSopenharmony_ci } 61648f512ceSopenharmony_ci } 61748f512ceSopenharmony_ci return true; 61848f512ceSopenharmony_ci} 61948f512ceSopenharmony_ci 62048f512ceSopenharmony_civoid SubCommandStat::SetPerfEvent() 62148f512ceSopenharmony_ci{ 62248f512ceSopenharmony_ci SetReportFlags(perCpus_, perThreads_); 62348f512ceSopenharmony_ci perfEvents_.SetSystemTarget(targetSystemWide_); 62448f512ceSopenharmony_ci perfEvents_.SetTimeOut(timeStopSec_); 62548f512ceSopenharmony_ci perfEvents_.SetTimeReport(timeReportMs_); 62648f512ceSopenharmony_ci perfEvents_.SetPerCpu(perCpus_); 62748f512ceSopenharmony_ci perfEvents_.SetPerThread(perThreads_); 62848f512ceSopenharmony_ci perfEvents_.SetVerboseReport(verboseReport_); 62948f512ceSopenharmony_ci perfEvents_.SetInherit(!noCreateNew_); 63048f512ceSopenharmony_ci perfEvents_.SetTrackedCommand(trackedCommand_); 63148f512ceSopenharmony_ci // set report handle 63248f512ceSopenharmony_ci perfEvents_.SetStatCallBack(Report); 63348f512ceSopenharmony_ci} 63448f512ceSopenharmony_ci 63548f512ceSopenharmony_cibool SubCommandStat::OnSubCommand(std::vector<std::string> &args) 63648f512ceSopenharmony_ci{ 63748f512ceSopenharmony_ci CHECK_TRUE(HelpOption(), true, 0, ""); 63848f512ceSopenharmony_ci if (!CheckRestartOption(appPackage_, targetSystemWide_, restart_, selectPids_)) { 63948f512ceSopenharmony_ci return false; 64048f512ceSopenharmony_ci } 64148f512ceSopenharmony_ci // check option 64248f512ceSopenharmony_ci if (!CheckSelectCpuPidOption()) { 64348f512ceSopenharmony_ci return false; 64448f512ceSopenharmony_ci } 64548f512ceSopenharmony_ci if (!CheckOptions(selectPids_)) { 64648f512ceSopenharmony_ci HLOGV("CheckOptions() failed"); 64748f512ceSopenharmony_ci return false; 64848f512ceSopenharmony_ci } 64948f512ceSopenharmony_ci if (!CheckAppIsRunning(selectPids_, appPackage_, checkAppMs_)) { 65048f512ceSopenharmony_ci HLOGV("CheckAppIsRunning() failed"); 65148f512ceSopenharmony_ci return false; 65248f512ceSopenharmony_ci } 65348f512ceSopenharmony_ci 65448f512ceSopenharmony_ci perfEvents_.SetCpu(selectCpus_); 65548f512ceSopenharmony_ci std::vector<pid_t> pids; 65648f512ceSopenharmony_ci for (auto selectPid : selectPids_) { 65748f512ceSopenharmony_ci HLOGD("[OnSubCommand] selectPid %d\n", selectPid); 65848f512ceSopenharmony_ci std::vector<pid_t> subTids = GetSubthreadIDs(selectPid, thread_map_); 65948f512ceSopenharmony_ci if (!subTids.empty()) { 66048f512ceSopenharmony_ci pids.insert(pids.end(), subTids.begin(), subTids.end()); 66148f512ceSopenharmony_ci } else { 66248f512ceSopenharmony_ci HLOGD("[OnSubCommand] subTids empty for %d\n", selectPid); 66348f512ceSopenharmony_ci } 66448f512ceSopenharmony_ci } 66548f512ceSopenharmony_ci pids.insert(pids.end(), selectTids_.begin(), selectTids_.end()); 66648f512ceSopenharmony_ci perfEvents_.SetPid(pids); 66748f512ceSopenharmony_ci if (!CheckOptionPidAndApp(pids)) { 66848f512ceSopenharmony_ci HLOGV("CheckOptionPidAndApp() failed"); 66948f512ceSopenharmony_ci return false; 67048f512ceSopenharmony_ci } 67148f512ceSopenharmony_ci SetPerfEvent(); 67248f512ceSopenharmony_ci if (!PrepairEvents()) { 67348f512ceSopenharmony_ci HLOGV("PrepairEvents() failed"); 67448f512ceSopenharmony_ci return false; 67548f512ceSopenharmony_ci } 67648f512ceSopenharmony_ci 67748f512ceSopenharmony_ci // preapare fd 67848f512ceSopenharmony_ci perfEvents_.PrepareTracking(); 67948f512ceSopenharmony_ci 68048f512ceSopenharmony_ci // start tracking 68148f512ceSopenharmony_ci perfEvents_.StartTracking(); 68248f512ceSopenharmony_ci 68348f512ceSopenharmony_ci return true; 68448f512ceSopenharmony_ci} 68548f512ceSopenharmony_ci 68648f512ceSopenharmony_cibool RegisterSubCommandStat() 68748f512ceSopenharmony_ci{ 68848f512ceSopenharmony_ci return SubCommand::RegisterSubCommand("stat", std::make_unique<SubCommandStat>()); 68948f512ceSopenharmony_ci} 69048f512ceSopenharmony_ci 69148f512ceSopenharmony_cibool SubCommandStat::PrepairEvents() 69248f512ceSopenharmony_ci{ 69348f512ceSopenharmony_ci if (selectEvents_.empty() && selectGroups_.empty()) { 69448f512ceSopenharmony_ci perfEvents_.AddDefaultEvent(PERF_TYPE_HARDWARE); 69548f512ceSopenharmony_ci perfEvents_.AddDefaultEvent(PERF_TYPE_SOFTWARE); 69648f512ceSopenharmony_ci } else { 69748f512ceSopenharmony_ci for (auto events : selectEvents_) { 69848f512ceSopenharmony_ci if (!perfEvents_.AddEvents(events)) { 69948f512ceSopenharmony_ci HLOGV("add events failed"); 70048f512ceSopenharmony_ci return false; 70148f512ceSopenharmony_ci } 70248f512ceSopenharmony_ci } 70348f512ceSopenharmony_ci for (auto events : selectGroups_) { 70448f512ceSopenharmony_ci if (!perfEvents_.AddEvents(events, true)) { 70548f512ceSopenharmony_ci HLOGV("add groups failed"); 70648f512ceSopenharmony_ci return false; 70748f512ceSopenharmony_ci } 70848f512ceSopenharmony_ci } 70948f512ceSopenharmony_ci } 71048f512ceSopenharmony_ci return true; 71148f512ceSopenharmony_ci} 71248f512ceSopenharmony_ci 71348f512ceSopenharmony_cibool SubCommandStat::CheckSelectCpuPidOption() 71448f512ceSopenharmony_ci{ 71548f512ceSopenharmony_ci if (!selectCpus_.empty()) { 71648f512ceSopenharmony_ci // the only value is not -1 71748f512ceSopenharmony_ci if (!(selectCpus_.size() == 1 && selectCpus_.front() == -1)) { 71848f512ceSopenharmony_ci int maxCpuid = sysconf(_SC_NPROCESSORS_CONF) - 1; 71948f512ceSopenharmony_ci for (auto cpu : selectCpus_) { 72048f512ceSopenharmony_ci if (cpu < 0 || cpu > maxCpuid) { 72148f512ceSopenharmony_ci printf("Invalid -c value '%d', the CPU ID should be in 0~%d \n", cpu, maxCpuid); 72248f512ceSopenharmony_ci return false; 72348f512ceSopenharmony_ci } 72448f512ceSopenharmony_ci } 72548f512ceSopenharmony_ci } 72648f512ceSopenharmony_ci } else { 72748f512ceSopenharmony_ci // the cpu default -1 72848f512ceSopenharmony_ci if (!targetSystemWide_) { 72948f512ceSopenharmony_ci selectCpus_.push_back(-1); 73048f512ceSopenharmony_ci } 73148f512ceSopenharmony_ci } 73248f512ceSopenharmony_ci 73348f512ceSopenharmony_ci if (!selectPids_.empty()) { 73448f512ceSopenharmony_ci for (auto pid : selectPids_) { 73548f512ceSopenharmony_ci if (pid <= 0) { 73648f512ceSopenharmony_ci printf("Invalid -p value '%d', the pid should be larger than 0\n", pid); 73748f512ceSopenharmony_ci return false; 73848f512ceSopenharmony_ci } 73948f512ceSopenharmony_ci } 74048f512ceSopenharmony_ci } 74148f512ceSopenharmony_ci if (!selectTids_.empty()) { 74248f512ceSopenharmony_ci for (auto tid : selectTids_) { 74348f512ceSopenharmony_ci if (tid <= 0) { 74448f512ceSopenharmony_ci printf("Invalid -t value '%d', the tid should be larger than 0\n", tid); 74548f512ceSopenharmony_ci return false; 74648f512ceSopenharmony_ci } 74748f512ceSopenharmony_ci } 74848f512ceSopenharmony_ci } 74948f512ceSopenharmony_ci return true; 75048f512ceSopenharmony_ci} 75148f512ceSopenharmony_ci 75248f512ceSopenharmony_cibool SubCommandStat::CheckOptions(const std::vector<pid_t> &pids) 75348f512ceSopenharmony_ci{ 75448f512ceSopenharmony_ci if (targetSystemWide_) { 75548f512ceSopenharmony_ci if (!pids.empty() || !selectTids_.empty()) { 75648f512ceSopenharmony_ci printf("You cannot specify -a and -t/-p at the same time\n"); 75748f512ceSopenharmony_ci return false; 75848f512ceSopenharmony_ci } 75948f512ceSopenharmony_ci if (!appPackage_.empty()) { 76048f512ceSopenharmony_ci printf("You cannot specify -a and --app at the same time\n"); 76148f512ceSopenharmony_ci return false; 76248f512ceSopenharmony_ci } 76348f512ceSopenharmony_ci } 76448f512ceSopenharmony_ci if (!appPackage_.empty() && (!pids.empty() || !selectTids_.empty())) { 76548f512ceSopenharmony_ci printf("You cannot specify --app and -t/-p at the same time\n"); 76648f512ceSopenharmony_ci return false; 76748f512ceSopenharmony_ci } 76848f512ceSopenharmony_ci if (!targetSystemWide_ && trackedCommand_.empty() && pids.empty() && appPackage_.empty() 76948f512ceSopenharmony_ci && selectTids_.empty()) { 77048f512ceSopenharmony_ci printf("You need to set the -p option or --app option.\n"); 77148f512ceSopenharmony_ci return false; 77248f512ceSopenharmony_ci } 77348f512ceSopenharmony_ci if (targetSystemWide_ && !trackedCommand_.empty()) { 77448f512ceSopenharmony_ci printf("You cannot specify -a and a cmd at the same time\n"); 77548f512ceSopenharmony_ci return false; 77648f512ceSopenharmony_ci } 77748f512ceSopenharmony_ci if (!trackedCommand_.empty()) { 77848f512ceSopenharmony_ci if (!pids.empty() || !selectTids_.empty()) { 77948f512ceSopenharmony_ci printf("You cannot specify a cmd and -t/-p at the same time\n"); 78048f512ceSopenharmony_ci return false; 78148f512ceSopenharmony_ci } 78248f512ceSopenharmony_ci if (!appPackage_.empty()) { 78348f512ceSopenharmony_ci printf("You cannot specify a cmd and --app at the same time\n"); 78448f512ceSopenharmony_ci return false; 78548f512ceSopenharmony_ci } 78648f512ceSopenharmony_ci if (!IsRoot()) { 78748f512ceSopenharmony_ci printf("%s options needs root privilege, please check usage\n", 78848f512ceSopenharmony_ci VectorToString(trackedCommand_).c_str()); 78948f512ceSopenharmony_ci return false; 79048f512ceSopenharmony_ci } 79148f512ceSopenharmony_ci } 79248f512ceSopenharmony_ci if (checkAppMs_ < MIN_CHECK_APP_MS || checkAppMs_ > MAX_CHECK_APP_MS) { 79348f512ceSopenharmony_ci printf("Invalid --chkms value '%d', the milliseconds should be in %d~%d \n", checkAppMs_, 79448f512ceSopenharmony_ci MIN_CHECK_APP_MS, MAX_CHECK_APP_MS); 79548f512ceSopenharmony_ci return false; 79648f512ceSopenharmony_ci } 79748f512ceSopenharmony_ci if (timeStopSec_ < 0) { 79848f512ceSopenharmony_ci printf("monitoring duration should be positive but %f is given\n", timeStopSec_); 79948f512ceSopenharmony_ci return false; 80048f512ceSopenharmony_ci } 80148f512ceSopenharmony_ci if (timeReportMs_ < 0) { 80248f512ceSopenharmony_ci printf("print interval should be non-negative but %d is given\n", timeReportMs_); 80348f512ceSopenharmony_ci return false; 80448f512ceSopenharmony_ci } 80548f512ceSopenharmony_ci return true; 80648f512ceSopenharmony_ci} 80748f512ceSopenharmony_ci} // namespace HiPerf 80848f512ceSopenharmony_ci} // namespace Developtools 80948f512ceSopenharmony_ci} // namespace OHOS 810