• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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