libperf: Add man pages
Change the man page generation to asciidoc, because it's easier to use and has been more commonly used in related projects. Remove the current rst pages. Add 3 man pages to have a base for more additions: libperf.3 - overall description libperf-counting.7 - counting basics explained on simple example libperf-sampling.7 - sampling basics explained on simple example The plan is to add more man pages to cover the basic API. The build generates html and man pages: $ cd tools/lib/perf/Documentation $ make ASCIIDOC libperf.xml XMLTO libperf.3 ASCIIDOC libperf-counting.xml XMLTO libperf-counting.7 ASCIIDOC libperf-sampling.xml XMLTO libperf-sampling.7 ASCIIDOC libperf.html ASCIIDOC libperf-counting.html ASCIIDOC libperf-sampling.html Add the following install targets: install-man - man pages install-html - html version of man pages install-examples - examples mentioned in the man pages Signed-off-by: Jiri Olsa <jolsa@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Michael Petlan <mpetlan@redhat.com> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lore.kernel.org/lkml/20191206210612.8676-3-jolsa@kernel.org Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:

committed by
Arnaldo Carvalho de Melo

parent
3ce311afb5
commit
81de3bf37a
243
tools/lib/perf/Documentation/libperf-sampling.txt
Normal file
243
tools/lib/perf/Documentation/libperf-sampling.txt
Normal file
@@ -0,0 +1,243 @@
|
||||
libperf-sampling(7)
|
||||
===================
|
||||
|
||||
NAME
|
||||
----
|
||||
libperf-sampling - sampling interface
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
The sampling interface provides API to meassure and get count for specific perf events.
|
||||
|
||||
The following test tries to explain count on `sampling.c` example.
|
||||
|
||||
It is by no means complete guide to sampling, but shows libperf basic API for sampling.
|
||||
|
||||
The `sampling.c` comes with libbperf package and can be compiled and run like:
|
||||
|
||||
[source,bash]
|
||||
--
|
||||
$ gcc -o sampling sampling.c -lperf
|
||||
$ sudo ./sampling
|
||||
cpu 0, pid 0, tid 0, ip ffffffffad06c4e6, period 1
|
||||
cpu 0, pid 4465, tid 4469, ip ffffffffad118748, period 18322959
|
||||
cpu 0, pid 0, tid 0, ip ffffffffad115722, period 33544846
|
||||
cpu 0, pid 4465, tid 4470, ip 7f84fe0cdad6, period 23687474
|
||||
cpu 0, pid 0, tid 0, ip ffffffffad9e0349, period 34255790
|
||||
cpu 0, pid 4465, tid 4469, ip ffffffffad136581, period 38664069
|
||||
cpu 0, pid 0, tid 0, ip ffffffffad9e55e2, period 21922384
|
||||
cpu 0, pid 4465, tid 4470, ip 7f84fe0ebebf, period 17655175
|
||||
...
|
||||
--
|
||||
|
||||
It requires root access, because it uses hardware cycles event.
|
||||
|
||||
The `sampling.c` example profiles/samples all CPUs with hardware cycles, in a nutshel it:
|
||||
|
||||
- creates events
|
||||
- adds them to the event list
|
||||
- opens and enables events through the event list
|
||||
- sleeps for 3 seconds
|
||||
- disables events
|
||||
- reads and displays recorded samples
|
||||
- destroys the event list
|
||||
|
||||
The first thing you need to do before using libperf is to call init function:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
12 static int libperf_print(enum libperf_print_level level,
|
||||
13 const char *fmt, va_list ap)
|
||||
14 {
|
||||
15 return vfprintf(stderr, fmt, ap);
|
||||
16 }
|
||||
|
||||
23 int main(int argc, char **argv)
|
||||
24 {
|
||||
...
|
||||
40 libperf_init(libperf_print);
|
||||
--
|
||||
|
||||
It will setup the library and sets function for debug output from library.
|
||||
|
||||
The `libperf_print` callback will receive any message with its debug level,
|
||||
defined as:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
enum libperf_print_level {
|
||||
LIBPERF_ERR,
|
||||
LIBPERF_WARN,
|
||||
LIBPERF_INFO,
|
||||
LIBPERF_DEBUG,
|
||||
LIBPERF_DEBUG2,
|
||||
LIBPERF_DEBUG3,
|
||||
};
|
||||
--
|
||||
|
||||
Once the setup is complete we start by defining cycles event using the `struct perf_event_attr`:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
29 struct perf_event_attr attr = {
|
||||
30 .type = PERF_TYPE_HARDWARE,
|
||||
31 .config = PERF_COUNT_HW_CPU_CYCLES,
|
||||
32 .disabled = 1,
|
||||
33 .freq = 1,
|
||||
34 .sample_freq = 10,
|
||||
35 .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD,
|
||||
36 };
|
||||
--
|
||||
|
||||
Next step is to prepare cpus map.
|
||||
|
||||
In this case we will monitor all the available CPUs:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
42 cpus = perf_cpu_map__new(NULL);
|
||||
43 if (!cpus) {
|
||||
44 fprintf(stderr, "failed to create cpus\n");
|
||||
45 return -1;
|
||||
46 }
|
||||
--
|
||||
|
||||
Now we create libperf's event list, which will serve as holder for the cycles event:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
48 evlist = perf_evlist__new();
|
||||
49 if (!evlist) {
|
||||
50 fprintf(stderr, "failed to create evlist\n");
|
||||
51 goto out_cpus;
|
||||
52 }
|
||||
--
|
||||
|
||||
We create libperf's event for the cycles attribute we defined earlier and add it to the list:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
54 evsel = perf_evsel__new(&attr);
|
||||
55 if (!evsel) {
|
||||
56 fprintf(stderr, "failed to create cycles\n");
|
||||
57 goto out_cpus;
|
||||
58 }
|
||||
59
|
||||
60 perf_evlist__add(evlist, evsel);
|
||||
--
|
||||
|
||||
Configure event list with the cpus map and open event:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
62 perf_evlist__set_maps(evlist, cpus, NULL);
|
||||
63
|
||||
64 err = perf_evlist__open(evlist);
|
||||
65 if (err) {
|
||||
66 fprintf(stderr, "failed to open evlist\n");
|
||||
67 goto out_evlist;
|
||||
68 }
|
||||
--
|
||||
|
||||
Once the events list is open, we can create memory maps AKA perf ring buffers:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
70 err = perf_evlist__mmap(evlist, 4);
|
||||
71 if (err) {
|
||||
72 fprintf(stderr, "failed to mmap evlist\n");
|
||||
73 goto out_evlist;
|
||||
74 }
|
||||
--
|
||||
|
||||
The event is created as disabled (note the `disabled = 1` assignment above),
|
||||
so we need to enable the events list explicitely.
|
||||
|
||||
From this moment the cycles event is sampling.
|
||||
|
||||
We will sleep for 3 seconds while the ring buffers get data from all CPUs, then we disable the events list.
|
||||
|
||||
[source,c]
|
||||
--
|
||||
76 perf_evlist__enable(evlist);
|
||||
77 sleep(3);
|
||||
78 perf_evlist__disable(evlist);
|
||||
--
|
||||
|
||||
Following code walks through the ring buffers and reads stored events/samples:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
80 perf_evlist__for_each_mmap(evlist, map, false) {
|
||||
81 if (perf_mmap__read_init(map) < 0)
|
||||
82 continue;
|
||||
83
|
||||
84 while ((event = perf_mmap__read_event(map)) != NULL) {
|
||||
|
||||
/* process event */
|
||||
|
||||
108 perf_mmap__consume(map);
|
||||
109 }
|
||||
110 perf_mmap__read_done(map);
|
||||
111 }
|
||||
|
||||
--
|
||||
|
||||
Each sample needs to get parsed:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
85 int cpu, pid, tid;
|
||||
86 __u64 ip, period, *array;
|
||||
87 union u64_swap u;
|
||||
88
|
||||
89 array = event->sample.array;
|
||||
90
|
||||
91 ip = *array;
|
||||
92 array++;
|
||||
93
|
||||
94 u.val64 = *array;
|
||||
95 pid = u.val32[0];
|
||||
96 tid = u.val32[1];
|
||||
97 array++;
|
||||
98
|
||||
99 u.val64 = *array;
|
||||
100 cpu = u.val32[0];
|
||||
101 array++;
|
||||
102
|
||||
103 period = *array;
|
||||
104
|
||||
105 fprintf(stdout, "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n",
|
||||
106 cpu, pid, tid, ip, period);
|
||||
--
|
||||
|
||||
And finaly cleanup.
|
||||
|
||||
We close the whole events list (both events) and remove it together with the threads map:
|
||||
|
||||
[source,c]
|
||||
--
|
||||
113 out_evlist:
|
||||
114 perf_evlist__delete(evlist);
|
||||
115 out_cpus:
|
||||
116 perf_cpu_map__put(cpus);
|
||||
117 return err;
|
||||
118 }
|
||||
--
|
||||
|
||||
REPORTING BUGS
|
||||
--------------
|
||||
Report bugs to <linux-perf-users@vger.kernel.org>.
|
||||
|
||||
LICENSE
|
||||
-------
|
||||
libperf is Free Software licensed under the GNU LGPL 2.1
|
||||
|
||||
RESOURCES
|
||||
---------
|
||||
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
libperf(3), libperf-counting(7)
|
Reference in New Issue
Block a user