• 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 
16 #ifndef SUBCOMMAND_REPORT_H
17 #define SUBCOMMAND_REPORT_H
18 
19 #include <algorithm>
20 #include <cstdlib>
21 #include <functional>
22 #include <map>
23 #include <optional>
24 #include <set>
25 #include <stdio.h>
26 #include <tuple>
27 #include <linux/perf_event.h>
28 
29 #include "perf_file_reader.h"
30 #if HAVE_PROTOBUF
31 #include "report_protobuf_file.h"
32 #endif
33 #include "debug_logger.h"
34 #include "option.h"
35 #include "perf_event_record.h"
36 #include "report.h"
37 #include "report_json_file.h"
38 #include "subcommand.h"
39 #include "symbols_file.h"
40 #include "utilities.h"
41 #include "virtual_runtime.h"
42 
43 namespace OHOS {
44 namespace Developtools {
45 namespace HiPerf {
46 class SubCommandReport : public SubCommand {
47 public:
SubCommandReport()48     SubCommandReport()
49         // clang-format off
50         : SubCommand("report", "report sampling information from perf.data format file",
51         "Usage: hiperf report [options]\n"
52         "       The default options are same as :\n"
53         "       -i perf.data --sort comm,pid,tid,dso,func\n"
54         "   --symbol-dir <dir>\n"
55         "       use symbols path to find symbols.\n"
56         "       separate the paths with commas.\n"
57         "   --limit-percent <number>\n"
58         "       only show heat percent limit content.\n"
59         "   -s / --call-stack\n"
60         "       show the unwind callstack\n"
61         "   --call-stack-limit-percent <number>\n"
62         "       only show the callstack heat percent limit content.\n"
63         "   --proto\n"
64         "       show protobuf content in the save file name.\n"
65         "       default file name is perf.data.\n"
66         "   --json\n"
67         "       report in json format.\n"
68         "       default file name is perf.data.\n"
69         "   --diff <target file>\n"
70         "       show the diff result from -i to -diff .\n"
71         "       example: \"report -i a.data --diff b.data\"\n"
72         "   --branch\n"
73         "       show the branch from address instead of ip address\n"
74         "   --<keys> <keyname1>[,keyname2][,...]\n"
75         "       select able keys: comms,pids,tids,dsos,funcs,from_dsos,from_funcs\n"
76         "           example: --comms hiperf\n"
77         "   --sort <key1>[,key2][,...]\n"
78         "       Choose some keywords.\n"
79         "       These keywords will be used for sorting.\n"
80         "       Only selected keywords will appear in the report.\n"
81         "\n"
82         "           pid             -- process id\n"
83         "           tid             -- thread id\n"
84         "           comm            -- thread name (can be changed for same thread)\n"
85         "           dso             -- like dso name , or elf path\n"
86         "           func            -- function name in the symbols\n"
87         "\n"
88         "       in branch mode:\n"
89         "           from_dso        -- branched from dso or elf\n"
90         "           from_func       -- branched from function\n"
91         "           dso             -- means branched to dso or elf\n"
92         "           func            -- means branched to function\n"
93         "   -i <filename>\n"
94         "           perf data file to report, default is perf.data\n"
95         "   -o <filename>\n"
96         "           report file name. if empty will use stdout print\n"
97         "   --hide_count\n"
98         "           will not show count in report\n"
99         "\n"
100         ), recordFile_ {"perf.data", ""} // default file path is perf.data
101     // clang-format on
102     {
103     }
104     bool OnSubCommand(std::vector<std::string> &args) override;
105     bool ParseOption(std::vector<std::string> &args) override;
106     void DumpOptions(void) const override;
107     static bool RegisterSubCommandReport(void);
108     bool RecordCallBack(std::unique_ptr<PerfEventRecord> record);
109 
110     ~SubCommandReport();
111 
112 private:
113     void ProcessSample(std::unique_ptr<PerfRecordSample> &);
114     void BroadcastSample(std::unique_ptr<PerfRecordSample> &);
115 
116     bool VerifyOption();
117     bool VerifyDisplayOption();
118 
119     // load
120     bool PrepareOutput();
121     bool LoadPerfData();
122     void ProcessFeaturesData();
123     void LoadEventConfigData();
124     void LoadAttrSection();
125     void LoadEventDesc();
126     void ProcessSymbolsData();
127     void LoadPerfDataCompleted();
128 
129     bool OutputReport();
130     bool OutputStd();
131 
132     // prefdata
133     bool showCallStack_ = false;
134     bool diffMode_ = false;
135 
136     // create record file reader pointer
137     std::unique_ptr<PerfFileReader> recordFileReader_;
138     std::vector<std::string> symbolsPaths_;
139 
140     // report file name , if empty will use stdout
141     std::string reportFile_;
142 
143     // for diff report
144     enum RecordIndex { FIRST = 0, SECOND = 1, MAX = 2, CURRENT = -1 } index_ = FIRST;
145     std::string recordFile_[MAX];
146     ReportOption reportOption_;
147     Report report_[MAX] = {reportOption_, reportOption_};
148     inline Report &GetReport(RecordIndex index = CURRENT, int configId = 0)
149     {
150         if (index == CURRENT) {
151             return report_[index_];
152         } else {
153             return report_[index];
154         }
155     }
156 
157     std::vector<std::string> configNames_;
158     std::set<uint64_t> cpuOffids_;
159 
160     const std::string cpuOffEventName = "sched:sched_switch";
161     bool cpuOffMode_ = false;
162     std::map<pid_t, std::unique_ptr<PerfRecordSample>> prevSampleCache_;
163     void FlushCacheRecord();
164 
165     // in debug mode we will output some more debug info
166     bool debug_ = false;
167     bool branch_ = false;
168     bool jsonFormat_ = false;
169 
170     FILE *output_ = nullptr;
171 
172     std::unique_ptr<ReportJsonFile> reportJsonFile_ = nullptr;
173 
174     bool protobufFormat_ = false;
175 #if HAVE_PROTOBUF
176     std::unique_ptr<ReportProtobufFileWriter> protobufOutputFileWriter_ = nullptr;
177     void UpdateReportInfo();
178 #endif
179     friend class SubCommandReportTest;
180     FRIEND_TEST(SubCommandReportTest, TestLoadPerfData);
181     FRIEND_TEST(SubCommandReportTest, TestOutputReport);
182     FRIEND_TEST(SubCommandReportTest, TestOutputStd);
183     FRIEND_TEST(SubCommandReportTest, TestVerifyOption);
184     FRIEND_TEST(SubCommandReportTest, TestVerifyDisplayOption);
185     FRIEND_TEST(SubCommandReportTest, TestPrepareConsole);
186     FRIEND_TEST(SubCommandReportTest, TestPrepareConsole);
187 };
188 } // namespace HiPerf
189 } // namespace Developtools
190 } // namespace OHOS
191 #endif // SUBCOMMAND_REPORT_H
192