Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1libperf-sampling(7)
2===================
3
4NAME
5----
6libperf-sampling - sampling interface
7
8
9DESCRIPTION
10-----------
11The sampling interface provides API to meassure and get count for specific perf events.
12
13The following test tries to explain count on `sampling.c` example.
14
15It is by no means complete guide to sampling, but shows libperf basic API for sampling.
16
17The `sampling.c` comes with libbperf package and can be compiled and run like:
18
19[source,bash]
20--
21$ gcc -o sampling sampling.c -lperf
22$ sudo ./sampling
23cpu 0, pid 0, tid 0, ip ffffffffad06c4e6, period 1
24cpu 0, pid 4465, tid 4469, ip ffffffffad118748, period 18322959
25cpu 0, pid 0, tid 0, ip ffffffffad115722, period 33544846
26cpu 0, pid 4465, tid 4470, ip 7f84fe0cdad6, period 23687474
27cpu 0, pid 0, tid 0, ip ffffffffad9e0349, period 34255790
28cpu 0, pid 4465, tid 4469, ip ffffffffad136581, period 38664069
29cpu 0, pid 0, tid 0, ip ffffffffad9e55e2, period 21922384
30cpu 0, pid 4465, tid 4470, ip 7f84fe0ebebf, period 17655175
31...
32--
33
34It requires root access, because it uses hardware cycles event.
35
36The `sampling.c` example profiles/samples all CPUs with hardware cycles, in a nutshel it:
37
38- creates events
39- adds them to the event list
40- opens and enables events through the event list
41- sleeps for 3 seconds
42- disables events
43- reads and displays recorded samples
44- destroys the event list
45
46The first thing you need to do before using libperf is to call init function:
47
48[source,c]
49--
50 12 static int libperf_print(enum libperf_print_level level,
51 13 const char *fmt, va_list ap)
52 14 {
53 15 return vfprintf(stderr, fmt, ap);
54 16 }
55
56 23 int main(int argc, char **argv)
57 24 {
58 ...
59 40 libperf_init(libperf_print);
60--
61
62It will setup the library and sets function for debug output from library.
63
64The `libperf_print` callback will receive any message with its debug level,
65defined as:
66
67[source,c]
68--
69enum libperf_print_level {
70 LIBPERF_ERR,
71 LIBPERF_WARN,
72 LIBPERF_INFO,
73 LIBPERF_DEBUG,
74 LIBPERF_DEBUG2,
75 LIBPERF_DEBUG3,
76};
77--
78
79Once the setup is complete we start by defining cycles event using the `struct perf_event_attr`:
80
81[source,c]
82--
83 29 struct perf_event_attr attr = {
84 30 .type = PERF_TYPE_HARDWARE,
85 31 .config = PERF_COUNT_HW_CPU_CYCLES,
86 32 .disabled = 1,
87 33 .freq = 1,
88 34 .sample_freq = 10,
89 35 .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD,
90 36 };
91--
92
93Next step is to prepare cpus map.
94
95In this case we will monitor all the available CPUs:
96
97[source,c]
98--
99 42 cpus = perf_cpu_map__new(NULL);
100 43 if (!cpus) {
101 44 fprintf(stderr, "failed to create cpus\n");
102 45 return -1;
103 46 }
104--
105
106Now we create libperf's event list, which will serve as holder for the cycles event:
107
108[source,c]
109--
110 48 evlist = perf_evlist__new();
111 49 if (!evlist) {
112 50 fprintf(stderr, "failed to create evlist\n");
113 51 goto out_cpus;
114 52 }
115--
116
117We create libperf's event for the cycles attribute we defined earlier and add it to the list:
118
119[source,c]
120--
121 54 evsel = perf_evsel__new(&attr);
122 55 if (!evsel) {
123 56 fprintf(stderr, "failed to create cycles\n");
124 57 goto out_cpus;
125 58 }
126 59
127 60 perf_evlist__add(evlist, evsel);
128--
129
130Configure event list with the cpus map and open event:
131
132[source,c]
133--
134 62 perf_evlist__set_maps(evlist, cpus, NULL);
135 63
136 64 err = perf_evlist__open(evlist);
137 65 if (err) {
138 66 fprintf(stderr, "failed to open evlist\n");
139 67 goto out_evlist;
140 68 }
141--
142
143Once the events list is open, we can create memory maps AKA perf ring buffers:
144
145[source,c]
146--
147 70 err = perf_evlist__mmap(evlist, 4);
148 71 if (err) {
149 72 fprintf(stderr, "failed to mmap evlist\n");
150 73 goto out_evlist;
151 74 }
152--
153
154The event is created as disabled (note the `disabled = 1` assignment above),
155so we need to enable the events list explicitely.
156
157From this moment the cycles event is sampling.
158
159We will sleep for 3 seconds while the ring buffers get data from all CPUs, then we disable the events list.
160
161[source,c]
162--
163 76 perf_evlist__enable(evlist);
164 77 sleep(3);
165 78 perf_evlist__disable(evlist);
166--
167
168Following code walks through the ring buffers and reads stored events/samples:
169
170[source,c]
171--
172 80 perf_evlist__for_each_mmap(evlist, map, false) {
173 81 if (perf_mmap__read_init(map) < 0)
174 82 continue;
175 83
176 84 while ((event = perf_mmap__read_event(map)) != NULL) {
177
178 /* process event */
179
180108 perf_mmap__consume(map);
181109 }
182110 perf_mmap__read_done(map);
183111 }
184
185--
186
187Each sample needs to get parsed:
188
189[source,c]
190--
191 85 int cpu, pid, tid;
192 86 __u64 ip, period, *array;
193 87 union u64_swap u;
194 88
195 89 array = event->sample.array;
196 90
197 91 ip = *array;
198 92 array++;
199 93
200 94 u.val64 = *array;
201 95 pid = u.val32[0];
202 96 tid = u.val32[1];
203 97 array++;
204 98
205 99 u.val64 = *array;
206100 cpu = u.val32[0];
207101 array++;
208102
209103 period = *array;
210104
211105 fprintf(stdout, "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n",
212106 cpu, pid, tid, ip, period);
213--
214
215And finaly cleanup.
216
217We close the whole events list (both events) and remove it together with the threads map:
218
219[source,c]
220--
221113 out_evlist:
222114 perf_evlist__delete(evlist);
223115 out_cpus:
224116 perf_cpu_map__put(cpus);
225117 return err;
226118 }
227--
228
229REPORTING BUGS
230--------------
231Report bugs to <linux-perf-users@vger.kernel.org>.
232
233LICENSE
234-------
235libperf is Free Software licensed under the GNU LGPL 2.1
236
237RESOURCES
238---------
239https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
240
241SEE ALSO
242--------
243libperf(3), libperf-counting(7)