• 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 HIPERF_CLIENT_H_
16 #define HIPERF_CLIENT_H_
17 
18 #include <chrono>
19 #include <string>
20 #include <vector>
21 
22 namespace OHOS {
23 namespace Developtools {
24 namespace HiPerf {
25 namespace HiperfClient {
26 static const std::string HiperfCommandName = "hiperf";
27 static const std::string SystemBinPath = "/system/bin/";
28 static const std::string TempBinPath = "/data/local/tmp/";
29 static const std::string CurrentPath = "./";
30 static const std::string PerfDataName = "perf.data";
31 
32 static const std::string ReplyOK = "OK\n";
33 static const std::string ReplyFAIL = "FAIL\n";
34 static const std::string ReplyStart = "START\n";
35 static const std::string ReplyStop = "STOP\n";
36 static const std::string ReplyPause = "PAUSE\n";
37 static const std::string ReplyResume = "RESUME\n";
38 static const std::string ReplyCheck = "CHECK\n";
39 
40 static const std::string CommandRecord = "record";
41 static const std::string ArgOutputPath = "-o";
42 static const std::string ArgDebug = "--verbose";
43 static const std::string ArgDebugMuch = "--much";
44 static const std::string ArgHilog = "--hilog";
45 static const std::string ArgPipeInput = "--pipe_input";
46 static const std::string ArgPipeOutput = "--pipe_output";
47 static const std::string ArgTargetSystemWide = "-a";
48 static const std::string ArgCompressData = "-z";
49 static const std::string ArgSelectCpus = "-c";
50 static const std::string ArgTimeStopSec = "-d";
51 static const std::string ArgFrequency = "-f";
52 static const std::string ArgPeriod = "--period";
53 static const std::string ArgSelectEvents = "-e";
54 static const std::string ArgSelectGroups = "-g";
55 static const std::string ArgNoInherit = "--no-inherit";
56 static const std::string ArgSelectPids = "-p";
57 static const std::string ArgSelectTids = "-t";
58 static const std::string ArgExcludePerf = "--exclude-hiperf";
59 static const std::string ArgCpuPercent = "--cpu-limit";
60 static const std::string ArgOffCPU = "--offcpu";
61 static const std::string ArgCallGraph = "--call-stack";
62 static const std::string ArgDelayUnwind = "--delay-unwind";
63 static const std::string ArgDisableUnwind = "--disable-unwind";
64 static const std::string ArgDisableCallstackMerge = "--disable-callstack-expand";
65 static const std::string ArgSymbolDir = "--symbol-dir";
66 static const std::string ArgOutputFilename = "-o";
67 static const std::string ArgDataLimit = "--data-limit";
68 static const std::string ArgAppPackage = "--app";
69 static const std::string ArgClockId = "--clockid";
70 static const std::string ArgVecBranchSampleTypes = "-j";
71 static const std::string ArgMmapPages = "-m";
72 
73 class RecordOption {
74 public:
75     /**
76      * Set output file name, default is perf.data
77      */
SetOutputFilename(const std::string & outputFilename)78     void SetOutputFilename(const std::string &outputFilename)
79     {
80         outputFileName_ = outputFilename;
81     }
82     /**
83      * Get output file name
84      */
GetOutputFileName()85     const std::string GetOutputFileName() const
86     {
87         return outputFileName_;
88     }
89 
90     /**
91      * Collect system-wide information for measures all processes/threads
92      * default is disable.
93      */
94     void SetTargetSystemWide(bool enable);
95     /**
96      * Compress record data. default is disable.
97      */
98     void SetCompressData(bool enable);
99     /**
100      * Specify cpu ID, cpu ID shoule be 0,1,2...
101      */
102     void SetSelectCpus(const std::vector<int> &cpus);
103     /**
104      * Stop in <timeStopSec> seconds. default is 10000 seconds
105      */
106     void SetTimeStopSec(int timeStopSec);
107     /**
108      * Set event sampling frequency. default is 4000 samples every second.
109      */
110     void SetFrequency(int frequency);
111     /**
112      * Set event sampling period for tracepoint events.
113      * recording one sample when <period> events happen.
114      * default is 1
115      */
116     void SetPeriod(int period);
117     /**
118      * Customize the name of the event that needs to be sampled.
119      */
120     void SetSelectEvents(const std::vector<std::string> &selectEvents);
121     /**
122      * Customize the name of the event that needs to be grouped.
123      * the function is added on the basis of the function of the SetSelectEvents().
124      */
125     void SetSelectGroups(const std::vector<std::string> &selectGroups);
126     /**
127      * Set to don't tracing child processes. default is disable
128      */
129     void SetNoInherit(bool enable);
130     /**
131      * Set the limit process id of the collection target.
132      * Conflicts with the SetTargetSystemWide(true).
133      */
134     void SetSelectPids(const std::vector<pid_t> &selectPids);
135     /**
136      * Set the limit thread id of the collection target.
137      * Conflicts with the SetTargetSystemWide(true).
138      */
139     void SetSelectTids(const std::vector<pid_t> &selectTids);
140     /**
141      * Set don’t record events issued by hiperf itself.
142      */
143     void SetExcludePerf(bool excludePerf);
144     /**
145      * Set the max percent of cpu time used for recording.
146      * percent is in range [1-100], default is 25
147      */
148     void SetCpuPercent(int cpuPercent);
149     /**
150      * Set tracing when threads are scheduled off cpu, default is disable
151      */
152     void SetOffCPU(bool offCPU);
153     /**
154      * Set call-graph (stack chain/backtrace) recording, Default is 'fp'.
155      * as the method to collect the information used to show the call graphs.
156      * the value can be:
157      *  fp: frame pointer
158      *  dwarf: DWARF's CFI - Call Frame Information
159      *      'dwarf,###' set sample stack size, size should be in 8~65528 and 8 byte aligned.
160      */
161     void SetCallGraph(const std::string &sampleTypes);
162     /**
163      * Set to unwind after recording.
164      * If '-g dwarf' used, stack will be unwind while recording by default
165      */
166     void SetDelayUnwind(bool delayUnwind);
167     /**
168      * Set to disable unwinding.
169      * If '-g dwarf' used, stack will be unwind while recording  by default
170      */
171     void SetDisableUnwind(bool disableUnwind);
172     /**
173      * Set callstack don't merged.
174      * If '-g dwarf' is used, to break the 64k stack limit, callstack is merged by default
175      */
176     void SetDisableCallstackMerge(bool disableCallstackMerge);
177     /**
178      * Set directory to look for symbol files, used for unwinding.
179      */
180     void SetSymbolDir(const std::string &symbolDir_);
181     /**
182      * Set to stop recording after <SIZE> bytes of records. Default is unlimited
183      * format like: SIZE[K|M|G]
184      */
185     void SetDataLimit(const std::string &limit);
186     /**
187      * Set a OHOS app name, collect profile info for this app, the app must be debuggable.
188      */
189     void SetAppPackage(const std::string &appPackage);
190     /**
191      * Set the clock id to use for the various time fields in the perf_event_type records.
192      */
193     void SetClockId(const std::string &clockId);
194     /**
195      * Set to take branch stack sampling, filter can be
196      *  any: any type of branch
197      *  any_call: any function call or system call
198      *  any_ret: any function return or system call return
199      *  ind_call: any indirect branch
200      *  call: direct calls, including far (to/from kernel) calls
201      *  u: only when the branch target is at the user level
202      *  k: only when the branch target is in the kernel\n"
203      */
204     void SetVecBranchSampleTypes(const std::vector<std::string> &vecBranchSampleTypes);
205     /**
206      * Set the size of the buffer used to receiving sample data from kernel,
207      * must be a power of two. If not set,  a value <=1024 will be used.
208      */
209     void SetMmapPages(int mmapPages);
210 
211     /**
212      * Get the string vector of all options.
213      */
GetOptionVecString()214     const std::vector<std::string> &GetOptionVecString() const
215     {
216         return args_;
217     }
218 
219 private:
220     std::vector<std::string> args_ = {};
221     std::string outputFileName_ = "";
222 
223     void SetOption(const std::string &name, bool enable);
224     void SetOption(const std::string &name, int value);
225     void SetOption(const std::string &name, const std::vector<int> &vInt);
226     void SetOption(const std::string &name, const std::string &str);
227     void SetOption(const std::string &name, const std::vector<std::string> &vStr);
228 };
229 
230 class Client {
231 public:
232     /**
233      * Set output dir and constuct
234      */
235     Client(const std::string &outputDir = TempBinPath);
236     ~Client();
237     /**
238      * Start record with default options
239      */
240     bool Start();
241     /**
242      * Start record with options of string vector
243      */
244     bool Start(const std::vector<std::string> &args);
245     /**
246      * Start record with options of RecordOption
247      */
248     bool Start(const RecordOption &option);
249     /**
250      * Pause recording
251      */
252     bool Pause();
253     /**
254      * Resume recording
255      */
256     bool Resume();
257     /**
258      * Stop recording
259      */
260     bool Stop();
261     /**
262      * Check the client is ready
263      */
264     bool IsReady();
265     /**
266      * Set the output dir
267      */
268     bool Setup(std::string outputDir);
269 
270     /**
271      * Get the output dir
272      */
GetOutputDir()273     const std::string &GetOutputDir() const
274     {
275         return outputDir_;
276     }
277     /**
278      * Get the command path
279      */
GetCommandPath()280     const std::string &GetCommandPath() const
281     {
282         return executeCommandPath_;
283     }
284     /**
285      * Get the the fullpath of output file
286      */
GetOutputPerfDataPath()287     const std::string GetOutputPerfDataPath() const
288     {
289         return outputDir_ + outputFileName_;
290     }
291 
292     void SetDebugMode();
293     void SetDebugMuchMode();
294     void EnableHilog();
295 
296 private:
297     static const uint64_t PIPE_READ = 0;
298     static const uint64_t PIPE_WRITE = 1;
299     static constexpr size_t SIZE_ARGV_TAIL = 1; // nullptr
300     static constexpr int64_t THOUSAND = 1000;
301 
302     bool WaitCommandReply(std::chrono::milliseconds = std::chrono::milliseconds(THOUSAND));
303     bool SendCommandAndWait(const std::string &cmd);
304     void KillChild();
305     void GetExecCmd(std::vector<std::string> &cmd, int pipeIn, int pipeOut,
306                     const std::vector<std::string> &args);
307 
308     std::string outputDir_ = "";
309     std::string outputFileName_ = "";
310     std::string executeCommandPath_ = "";
311     bool ready_ = false;
312     pid_t myPid_ = -1;
313     bool debug_ = false;
314     bool debugMuch_ = false;
315     bool hilog_ = false;
316 
317     int clientToServerFd_ = -1;
318     int serverToClientFd_ = -1;
319     pid_t hperfPid_ = -1;
320 };
321 } // namespace HiperfClient
322 } // namespace HiPerf
323 } // namespace Developtools
324 } // namespace OHOS
325 #endif