1 /* 2 * Copyright (c) 2021-2022 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 #ifndef SUBCOMMAND_STAT_H_ 16 #define SUBCOMMAND_STAT_H_ 17 18 #include "option.h" 19 #include "perf_events.h" 20 #include "perf_pipe.h" 21 #include "subcommand.h" 22 23 namespace OHOS { 24 namespace Developtools { 25 namespace HiPerf { 26 class SubCommandStat : public SubCommand { 27 public: 28 static constexpr int DEFAULT_CHECK_APP_MS = 10; 29 static constexpr int MIN_CHECK_APP_MS = 1; 30 static constexpr int MAX_CHECK_APP_MS = 200; 31 ~SubCommandStat(); SubCommandStat()32 SubCommandStat() 33 : SubCommand("stat", "Collect performance counter information", 34 // clang-format off 35 "Usage: hiperf stat [options] [command [command-args]]\n" 36 " Collect performance counter information of running [command].\n" 37 " The default options are: -c -1 -d 10000.0\n" 38 " -a\n" 39 " Collect system-wide information.\n" 40 " for measures all processes/threads\n" 41 " This requires CAP_PERFMON (since Linux 5.8) or\n" 42 " CAP_SYS_ADMIN capability or a\n" 43 " /proc/sys/kernel/perf_event_paranoid value of less than 1.\n" 44 " -c <cpuid>[<,cpuid>]\n" 45 " cpuid should be 0,1,2...\n" 46 " Limit the CPU that collects data.\n" 47 " 0 means cpu0, 1 means cpu1 ...\n" 48 " -d <sec>\n" 49 " stop in <sec> seconds.\n" 50 " floating point number.\n" 51 " default is 10000.0\n" 52 " -i <ms>\n" 53 " print stat info every <ms>.\n" 54 " -e event1[:<u|k>][,event1[:<u|k>]]...\n" 55 " Customize the name of the event that needs to be counted.\n" 56 " The name can use the names listed in the list parameter.\n" 57 " It can also be represented by the value of 0x<hex>.\n" 58 " u - monitor user space events only\n" 59 " k - monitor kernel space events only\n" 60 " -g <event1[:<u|k>]>[,event1[:<u|k>]]...\n" 61 " The grouping function is added on the basis of the function of the -e parameter\n" 62 " PMU is required to report data in designated groups\n" 63 " limited by HW capability, too many events cannot be reported in the same sampling)\n" 64 " --no-inherit\n" 65 " Don't track new processes/threads.\n" 66 " -p <pid1>[,pid2]...\n" 67 " Limit the process id of the collection target. Conflicts with the -a option.\n" 68 " -t <tid1>[,tid2]...\n" 69 " Limit the thread id of the collection target. Conflicts with the -a option.\n" 70 " --app <package_name>\n" 71 " Collect profile info for an OHOS app, the app must be debuggable.\n" 72 " Record will exit if the process is not started within 10 seconds.\n" 73 " --chkms <millisec>\n" 74 " Set the interval of querying the <package_name>.\n" 75 " <millisec> is in range [1-200], default is 10.\n" 76 " --per-core\n" 77 " Print counters for each cpu core.\n" 78 " --per-thread\n" 79 " Print counters for each thread.\n" 80 " --restart\n" 81 " Collect performance counter information of application startup.\n" 82 " Record will exit if the process is not started within 30 seconds.\n" 83 " --verbose\n" 84 " Show more detailed reports.\n" 85 " --dumpoptions\n" 86 " Dump command options.\n" 87 " --control <command>\n" 88 " Control counting by <command>, the <command> can be:\n" 89 " prepare: set arguments and prepare counting\n" 90 " start: start counting\n" 91 " stop: stop counting\n" 92 " -o <output_file_name>\n" 93 " Set output file name, default is /data/local/tmp/perf_stat.txt.\n" 94 " Only restrain using with --control prepare.\n" 95 // clang-format on 96 ), 97 targetSystemWide_(false) 98 { 99 } 100 HiperfError OnSubCommand(std::vector<std::string>& args) override; 101 bool ParseOption(std::vector<std::string> &args) override; 102 bool ParseSpecialOption(std::vector<std::string> &args); 103 void DumpOptions(void) const override; 104 105 // add args for hisysevent 106 void AddReportArgs(CommandReporter& reporter) override; 107 108 static SubCommand& GetInstance(); 109 110 private: 111 PerfEvents perfEvents_; 112 PerfPipe perfPipe_; 113 bool targetSystemWide_ {false}; 114 std::vector<int> selectCpus_ = {}; 115 float timeStopSec_ = PerfEvents::DEFAULT_TIMEOUT; 116 int timeReportMs_ {0}; 117 std::vector<std::vector<std::string>> selectEvents_; 118 std::vector<std::vector<std::string>> selectGroups_; 119 bool restart_ {false}; 120 bool noCreateNew_ {false}; 121 std::string appPackage_ = {}; 122 std::string outputFilename_ = ""; 123 std::string fifoFileC2S_; 124 std::string fifoFileS2C_; 125 int checkAppMs_ = DEFAULT_CHECK_APP_MS; 126 std::vector<pid_t> selectPids_; 127 std::vector<pid_t> selectTids_; 128 std::vector<pid_t> inputPidTidArgs_ = {}; 129 bool perCpus_ {false}; 130 bool perThreads_ {false}; 131 bool verboseReport_ {false}; 132 std::vector<std::string> trackedCommand_ {}; 133 bool helpOption_ {false}; 134 bool CheckOptionPidAndApp(const std::vector<pid_t>& pids); 135 bool CheckOptionPid(const std::vector<pid_t>& pids); 136 bool CheckOutPutFile(); 137 static bool FindEventCount( 138 const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents, 139 const std::string &configName, const __u64 group_id, __u64 &eventcount, double &scale); 140 static void GetComments( 141 const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents, 142 std::map<std::string, std::string> &comments); 143 static bool FindRunningTime( 144 const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents, 145 double &running_time_in_sec, __u64 &group_id, double &main_scale); 146 static bool IsMonitoredAtAllTime(const double &scale); 147 static std::string GetCommentConfigName( 148 const std::unique_ptr<PerfEvents::CountEvent> &countEvent, const std::string &eventName); 149 150 static void Report(const std::map<std::string, 151 std::unique_ptr<PerfEvents::CountEvent>> &countEvents, FILE* filePtr); 152 static void PrintPerHead(FILE* filePtr); 153 static void GetPerKey(std::string &perKey, const PerfEvents::Summary &summary); 154 static void MakeComments(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, std::string &commentStr); 155 static void ReportNormal(const std::map<std::string, 156 std::unique_ptr<PerfEvents::CountEvent>> &countEvents, FILE* filePtr); 157 static void ReportDetailInfos(const std::map<std::string, 158 std::unique_ptr<PerfEvents::CountEvent>> &countEvents, FILE* filePtr); 159 static void PrintPerValue(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, const float &ratio, 160 const std::string &configName, FILE* filePtr); 161 static void InitPerMap(const std::unique_ptr<PerfEvents::ReportSum> &newPerMap, 162 const PerfEvents::Summary &summary, VirtualRuntime& virtualInstance); 163 static bool FindPerCoreEventCount(PerfEvents::Summary &summary, __u64 &eventCount, double &scale); 164 static bool FindPercoreRunningTime(PerfEvents::Summary &summary, double &running_time_in_sec, double &main_scale); 165 static std::string GetDetailComments(const std::unique_ptr<PerfEvents::CountEvent> &countEvent, double &comment, 166 PerfEvents::Summary &summary, std::string &configName); 167 static std::string HandleOtherConfig(double &comment, PerfEvents::Summary &summary, 168 const double running_time_in_sec, const double scale, 169 const bool findRunningTime); 170 171 void PrintUsage(); HelpOption()172 inline bool HelpOption() 173 { 174 return helpOption_; 175 } 176 bool PrepairEvents(); 177 bool CheckOptions(const std::vector<pid_t> &pids); 178 bool CheckSelectCpuPidOption(); 179 void SetReportFlags(const bool cpuFlag, const bool threadFlag); 180 void SetPerfEvent(); 181 HiperfError CheckStatOption(); 182 183 // for client 184 int clientPipeInput_ = -1; 185 int clientPipeOutput_ = -1; 186 int nullFd_ = -1; 187 FILE* filePtr_ = nullptr; 188 std::thread clientCommandHandle_; 189 std::atomic_bool clientRunning_ = true; 190 struct ControlCommandHandler { 191 std::function<bool()> preProcess = []() -> bool { 192 return false; 193 }; 194 std::function<void(bool)> postProcess = [](bool) {}; 195 }; 196 std::unordered_map<std::string, ControlCommandHandler> controlCommandHandlerMap_ = {}; 197 inline void CreateClientThread(); 198 void ClientCommandHandle(); 199 void InitControlCommandHandlerMap(); 200 void DispatchControlCommand(const std::string& command); 201 bool ClientCommandResponse(const bool response); 202 bool ClientCommandResponse(const std::string& str); 203 bool IsSamplingRunning(); 204 205 // for cmdline client 206 bool allowIpc_ = true; 207 bool isFifoServer_ = false; 208 bool isFifoClient_ = false; 209 std::string controlCmd_ = {}; 210 bool ProcessControl(); 211 bool CreateFifoServer(); 212 bool ParseControlCmd(const std::string& cmd); 213 void CloseClientThread(); 214 }; 215 216 bool RegisterSubCommandStat(void); 217 } // namespace HiPerf 218 } // namespace Developtools 219 } // namespace OHOS 220 #endif // SUBCOMMAND_STAT_H_ 221