1LIBPERF-SAMPLING(7)             libperf Manual             LIBPERF-SAMPLING(7)
2
3
4

NAME

6       libperf-sampling - sampling interface
7

DESCRIPTION

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

REPORTING BUGS

207       Report bugs to <linux-perf-users@vger.kernel.org[1]>.
208

LICENSE

210       libperf is Free Software licensed under the GNU LGPL 2.1
211

RESOURCES

213       https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
214

SEE ALSO

216       libperf(3), libperf-counting(7)
217

NOTES

219        1. linux-perf-users@vger.kernel.org
220           mailto:linux-perf-users@vger.kernel.org
221
222
223
224libperf                           01/12/2023               LIBPERF-SAMPLING(7)
Impressum