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 "subcommand.h"
21
22namespace OHOS {
23namespace Developtools {
24namespace HiPerf {
25class SubCommandStat : public SubCommand {
26public:
27    static constexpr int DEFAULT_CHECK_APP_MS = 10;
28    static constexpr int MIN_CHECK_APP_MS = 1;
29    static constexpr int MAX_CHECK_APP_MS = 200;
30    SubCommandStat()
31        : SubCommand("stat", "Collect performance counter information",
32                     // clang-format off
33        "Usage: hiperf stat [options] [command [command-args]]\n"
34        "       Collect performance counter information of running [command].\n"
35        "       The default options are: -c -1 -d 10000.0\n"
36        "   -a\n"
37        "         Collect system-wide information.\n"
38        "         for measures all processes/threads\n"
39        "         This requires CAP_PERFMON (since Linux 5.8) or\n"
40        "          CAP_SYS_ADMIN capability or a\n"
41        "         /proc/sys/kernel/perf_event_paranoid value of less than 1.\n"
42        "   -c <cpuid>[<,cpuid>]\n"
43        "         cpuid should be 0,1,2...\n"
44        "         Limit the CPU that collects data.\n"
45        "         0 means cpu0, 1 means cpu1 ...\n"
46        "   -d <sec>\n"
47        "         stop in <sec> seconds.\n"
48        "         floating point number.\n"
49        "         default is 10000.0\n"
50        "   -i <ms>\n"
51        "         print stat info every <ms>.\n"
52        "   -e event1[:<u|k>][,event1[:<u|k>]]...\n"
53        "         Customize the name of the event that needs to be counted.\n"
54        "         The name can use the names listed in the list parameter.\n"
55        "         It can also be represented by the value of 0x<hex>.\n"
56        "            u - monitor user space events only\n"
57        "            k - monitor kernel space events only\n"
58        "   -g <event1[:<u|k>]>[,event1[:<u|k>]]...\n"
59        "         The grouping function is added on the basis of the function of the -e parameter\n"
60        "         PMU is required to report data in designated groups\n"
61        "         limited by HW capability, too many events cannot be reported in the same sampling)\n"
62        "   --no-inherit\n"
63        "         Don't track new processes/threads.\n"
64        "   -p <pid1>[,pid2]...\n"
65        "         Limit the process id of the collection target. Conflicts with the -a option.\n"
66        "   -t <tid1>[,tid2]...\n"
67        "         Limit the thread id of the collection target. Conflicts with the -a option.\n"
68        "   --app <package_name>\n"
69        "         Collect profile info for an OHOS app, the app must be debuggable.\n"
70        "         Record will exit if the process is not started within 10 seconds.\n"
71        "   --chkms <millisec>\n"
72        "         Set the interval of querying the <package_name>.\n"
73        "         <millisec> is in range [1-200], default is 10.\n"
74        "   --per-core\n"
75        "         Print counters for each cpu core.\n"
76        "   --per-thread\n"
77        "         Print counters for each thread.\n"
78        "   --restart\n"
79        "         Collect performance counter information of application startup.\n"
80        "         Record will exit if the process is not started within 30 seconds.\n"
81        "   --verbose\n"
82        "         Show more detailed reports.\n"
83        "   --dumpoptions\n"
84        "         Dump command options.\n"
85                     // clang-format on
86                     ),
87          targetSystemWide_(false)
88    {
89    }
90
91    bool OnSubCommand(std::vector<std::string> &args) override;
92    bool ParseOption(std::vector<std::string> &args) override;
93    bool ParseSpecialOption(std::vector<std::string> &args);
94    void DumpOptions(void) const override;
95
96private:
97    PerfEvents perfEvents_;
98    bool targetSystemWide_ {false};
99    std::vector<int> selectCpus_ = {};
100    float timeStopSec_ = PerfEvents::DEFAULT_TIMEOUT;
101    int timeReportMs_ {0};
102    std::vector<std::vector<std::string>> selectEvents_;
103    std::vector<std::vector<std::string>> selectGroups_;
104    bool restart_ {false};
105    bool noCreateNew_ {false};
106    std::string appPackage_ = {};
107    int checkAppMs_ = DEFAULT_CHECK_APP_MS;
108    std::vector<pid_t> selectPids_;
109    std::vector<pid_t> selectTids_;
110    bool perCpus_ {false};
111    bool perThreads_ {false};
112    bool verboseReport_ {false};
113    std::vector<std::string> trackedCommand_ {};
114    bool helpOption_ {false};
115    bool CheckOptionPidAndApp(std::vector<pid_t> pids);
116    bool CheckOptionPid(std::vector<pid_t> pids);
117    static bool FindEventCount(
118        const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents,
119        const std::string &configName, const __u64 group_id, __u64 &eventcount, double &scale);
120    static void GetComments(
121        const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents,
122        std::map<std::string, std::string> &comments);
123    static bool FindRunningTime(
124        const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents,
125        double &running_time_in_sec, __u64 &group_id, double &main_scale);
126    static bool IsMonitoredAtAllTime(const double &scale);
127    static std::string GetCommentConfigName(
128        const std::unique_ptr<PerfEvents::CountEvent> &countEvent, std::string eventName);
129
130    static void Report(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents);
131    static void PrintPerHead();
132    static void GetPerKey(std::string &perKey, const PerfEvents::Summary &summary);
133    static void MakeComments(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, std::string &commentStr);
134    static void ReportNormal(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents);
135    static void ReportDetailInfos(const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents);
136    static void PrintPerValue(const std::unique_ptr<PerfEvents::ReportSum> &reportSum, const float &ratio,
137                              std::string &configName);
138    static void InitPerMap(const std::unique_ptr<PerfEvents::ReportSum> &newPerMap,
139                           const PerfEvents::Summary &summary, VirtualRuntime& virtualInstance);
140    static bool FindPerCoreEventCount(PerfEvents::Summary &summary, __u64 &eventCount, double &scale);
141    static bool FindPercoreRunningTime(PerfEvents::Summary &summary, double &running_time_in_sec, double &main_scale);
142    static std::string GetDetailComments(const std::unique_ptr<PerfEvents::CountEvent> &countEvent, double &comment,
143                                  PerfEvents::Summary &summary, std::string &configName);
144    static std::string HandleOtherConfig(double &comment, PerfEvents::Summary &summary,
145                                         double running_time_in_sec, double scale, bool findRunningTime);
146
147    void PrintUsage();
148    inline bool HelpOption()
149    {
150        return helpOption_;
151    }
152    bool PrepairEvents();
153    bool CheckOptions(const std::vector<pid_t> &pids);
154    bool CheckSelectCpuPidOption();
155    void SetReportFlags(bool cpuFlag, bool threadFlag);
156    void SetPerfEvent();
157};
158
159bool RegisterSubCommandStat(void);
160} // namespace HiPerf
161} // namespace Developtools
162} // namespace OHOS
163#endif // SUBCOMMAND_STAT_H_
164