• 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 static const std::string ArgDedupStack = "--dedup_stack";
73 
74 static const int DEFAULT_DURATION_TIME = 10;
75 static const int DEFAULT_FREQUENCY_TIME = 100;
76 
77 #define HIPERF_EXIT_CODE 0
78 
79 class RecordOption {
80 public:
81     /**
82      * Set output file name, default is perf.data
83      */
SetOutputFilename(const std::string & outputFilename)84     void SetOutputFilename(const std::string &outputFilename)
85     {
86         outputFileName_ = outputFilename;
87     }
88     /**
89      * Get output file name
90      */
GetOutputFileName()91     const std::string GetOutputFileName() const
92     {
93         return outputFileName_;
94     }
95 
96     /**
97      * Get the default events for select.
98      */
GetSelectEvents()99     const std::vector<std::string> &GetSelectEvents() const
100     {
101         return selectEvents_;
102     }
103 
104     /**
105      * Collect system-wide information for measures all processes/threads
106      * default is disable.
107      */
108     void SetTargetSystemWide(bool enable);
109     /**
110      * Compress record data. default is disable.
111      */
112     void SetCompressData(bool enable);
113     /**
114      * Specify cpu ID, cpu ID shoule be 0,1,2...
115      */
116     void SetSelectCpus(const std::vector<int> &cpus);
117     /**
118      * Stop in <timeStopSec> seconds. default is 10000 seconds
119      */
120     void SetTimeStopSec(int timeStopSec);
121     /**
122      * Set event sampling frequency. default is 4000 samples every second.
123      */
124     void SetFrequency(int frequency);
125     /**
126      * Set event sampling period for tracepoint events.
127      * recording one sample when <period> events happen.
128      * default is 1
129      */
130     void SetPeriod(int period);
131     /**
132      * Customize the name of the event that needs to be sampled.
133      */
134     void SetSelectEvents(const std::vector<std::string> &selectEvents);
135     /**
136      * Customize the name of the event that needs to be grouped.
137      * the function is added on the basis of the function of the SetSelectEvents().
138      */
139     void SetSelectGroups(const std::vector<std::string> &selectGroups);
140     /**
141      * Set to don't tracing child processes. default is disable
142      */
143     void SetNoInherit(bool enable);
144     /**
145      * Set the limit process id of the collection target.
146      * Conflicts with the SetTargetSystemWide(true).
147      */
148     void SetSelectPids(const std::vector<pid_t> &selectPids);
149     /**
150      * Set default sampling parameters with specifying the select duration.
151      * default is 10 seconds.
152      */
153     void SetCallStackSamplingConfigs(int duration);
154     /**
155      * Set the limit thread id of the collection target.
156      * Conflicts with the SetTargetSystemWide(true).
157      */
158     void SetSelectTids(const std::vector<pid_t> &selectTids);
159     /**
160      * Set don’t record events issued by hiperf itself.
161      */
162     void SetExcludePerf(bool excludePerf);
163     /**
164      * Set the max percent of cpu time used for recording.
165      * percent is in range [1-100], default is 25
166      */
167     void SetCpuPercent(int cpuPercent);
168     /**
169      * Set tracing when threads are scheduled off cpu, default is disable
170      */
171     void SetOffCPU(bool offCPU);
172     /**
173      * Set call-graph (stack chain/backtrace) recording, Default is 'fp'.
174      * as the method to collect the information used to show the call graphs.
175      * the value can be:
176      *  fp: frame pointer
177      *  dwarf: DWARF's CFI - Call Frame Information
178      *      'dwarf,###' set sample stack size, size should be in 8~65528 and 8 byte aligned.
179      */
180     void SetCallGraph(const std::string &sampleTypes);
181     /**
182      * Set to unwind after recording.
183      * If '-g dwarf' used, stack will be unwind while recording by default
184      */
185     void SetDelayUnwind(bool delayUnwind);
186     /**
187      * Set to disable unwinding.
188      * If '-g dwarf' used, stack will be unwind while recording  by default
189      */
190     void SetDisableUnwind(bool disableUnwind);
191     /**
192      * Set callstack don't merged.
193      * If '-g dwarf' is used, to break the 64k stack limit, callstack is merged by default
194      */
195     void SetDisableCallstackMerge(bool disableCallstackMerge);
196     /**
197      * Set directory to look for symbol files, used for unwinding.
198      */
199     void SetSymbolDir(const std::string &symbolDir_);
200     /**
201      * Set to stop recording after <SIZE> bytes of records. Default is unlimited
202      * format like: SIZE[K|M|G]
203      */
204     void SetDataLimit(const std::string &limit);
205     /**
206      * Set a OHOS app name, collect profile info for this app, the app must be debuggable.
207      */
208     void SetAppPackage(const std::string &appPackage);
209     /**
210      * Set the clock id to use for the various time fields in the perf_event_type records.
211      */
212     void SetClockId(const std::string &clockId);
213     /**
214      * Set to take branch stack sampling, filter can be
215      *  any: any type of branch
216      *  any_call: any function call or system call
217      *  any_ret: any function return or system call return
218      *  ind_call: any indirect branch
219      *  call: direct calls, including far (to/from kernel) calls
220      *  u: only when the branch target is at the user level
221      *  k: only when the branch target is in the kernel\n"
222      */
223     void SetVecBranchSampleTypes(const std::vector<std::string> &vecBranchSampleTypes);
224     /**
225      * Set the size of the buffer used to receiving sample data from kernel,
226      * must be a power of two. If not set,  a value <=1024 will be used.
227      */
228     void SetMmapPages(int mmapPages);
229 
230     /**
231      * Get the string vector of all options.
232      */
GetOptionVecString()233     const std::vector<std::string> &GetOptionVecString() const
234     {
235         return args_;
236     }
237 
238     /**
239      * Get TimeSpec attribute
240      */
IsTimeSpecified()241     bool IsTimeSpecified() const
242     {
243         return timeSpec_;
244     }
245 private:
246     bool timeSpec_ = false;
247     std::vector<std::string> args_ = {};
248     std::vector<std::string> selectEvents_ = {"hw-cpu-cycles:u"};
249     std::string outputFileName_ = "";
250 
251     void SetOption(const std::string &name, bool enable);
252     void SetOption(const std::string &name, int value);
253     void SetOption(const std::string &name, const std::vector<int> &vInt);
254     void SetOption(const std::string &name, const std::string &str);
255     void SetOption(const std::string &name, const std::vector<std::string> &vStr);
256 };
257 
258 class Client {
259 public:
260     /**
261      * Set output dir and constuct
262      */
263     Client(const std::string &outputDir = TempBinPath);
264     ~Client();
265     /**
266      * Start record with default options
267      */
268     bool Start();
269     /**
270      * Start record with options of string vector
271      */
272     bool Start(const std::vector<std::string> &args);
273     /**
274      * Start record with options of RecordOption
275      */
276     bool Start(const RecordOption &option);
277     /**
278      * Start record synchronizely with specified time
279      */
280     bool RunHiperfCmdSync(const RecordOption &option);
281     /**
282      * Pause recording
283      */
284     bool Pause();
285     /**
286      * Resume recording
287      */
288     bool Resume();
289     /**
290      * Stop recording
291      */
292     bool Stop();
293     /**
294      * Check the client is ready
295      */
296     bool IsReady();
297     /**
298      * Set the output dir
299      */
300     bool Setup(std::string outputDir);
301 
302     /**
303      * Get the output dir
304      */
GetOutputDir()305     const std::string &GetOutputDir() const
306     {
307         return outputDir_;
308     }
309     /**
310      * Get the command path
311      */
GetCommandPath()312     const std::string &GetCommandPath() const
313     {
314         return executeCommandPath_;
315     }
316     /**
317      * Get the the fullpath of output file
318      */
GetOutputPerfDataPath()319     const std::string GetOutputPerfDataPath() const
320     {
321         return outputDir_ + outputFileName_;
322     }
323 
324     /**
325      * Child run execv cmd
326      */
327     void ChildRunExecv(std::vector<std::string> &cmd);
328     /**
329      * Prepare execv cmd
330      */
331     void PrepareExecCmd(std::vector<std::string> &cmd);
332     /**
333      * Parent wait for child exit
334      */
335     bool ParentWait(pid_t &wpid, int &childStatus);
336     void SetDebugMode();
337     void SetDebugMuchMode();
338     void EnableHilog();
339 
340 private:
341     static const uint64_t PIPE_READ = 0;
342     static const uint64_t PIPE_WRITE = 1;
343     static constexpr size_t SIZE_ARGV_TAIL = 1; // nullptr
344     static constexpr int64_t THOUSAND = 1000;
345 
346     bool WaitCommandReply(std::chrono::milliseconds = std::chrono::milliseconds(THOUSAND));
347     bool SendCommandAndWait(const std::string &cmd);
348     void KillChild();
349     void GetExecCmd(std::vector<std::string> &cmd, int pipeIn, int pipeOut,
350                     const std::vector<std::string> &args);
351 
352     void GetExecCmd(std::vector<std::string> &cmd,
353                     const std::vector<std::string> &args);
354     std::string outputDir_ = "";
355     std::string outputFileName_ = "";
356     std::string executeCommandPath_ = "";
357     bool ready_ = false;
358     pid_t myPid_ = -1;
359     bool debug_ = false;
360     bool debugMuch_ = false;
361     bool hilog_ = false;
362 
363     int clientToServerFd_ = -1;
364     int serverToClientFd_ = -1;
365     pid_t hperfPid_ = -1;
366 };
367 } // namespace HiperfClient
368 } // namespace HiPerf
369 } // namespace Developtools
370 } // namespace OHOS
371 #endif // HIPERF_CLIENT_H_
372