6 libperf-sampling - sampling interface
11 The sampling interface provides API to measure and get count for specific perf events.
13 The following test tries to explain count on `sampling.c` example.
15 It is by no means complete guide to sampling, but shows libperf basic API for sampling.
17 The `sampling.c` comes with libperf package and can be compiled and run like:
21 $ gcc -o sampling sampling.c -lperf
23 cpu 0, pid 0, tid 0, ip ffffffffad06c4e6, period 1
24 cpu 0, pid 4465, tid 4469, ip ffffffffad118748, period 18322959
25 cpu 0, pid 0, tid 0, ip ffffffffad115722, period 33544846
26 cpu 0, pid 4465, tid 4470, ip 7f84fe0cdad6, period 23687474
27 cpu 0, pid 0, tid 0, ip ffffffffad9e0349, period 34255790
28 cpu 0, pid 4465, tid 4469, ip ffffffffad136581, period 38664069
29 cpu 0, pid 0, tid 0, ip ffffffffad9e55e2, period 21922384
30 cpu 0, pid 4465, tid 4470, ip 7f84fe0ebebf, period 17655175
34 It requires root access, because it uses hardware cycles event.
36 The `sampling.c` example profiles/samples all CPUs with hardware cycles, in a
40 - adds them to the event list
41 - opens and enables events through the event list
42 - sleeps for 3 seconds
44 - reads and displays recorded samples
45 - destroys the event list
47 The first thing you need to do before using libperf is to call init function:
51 12 static int libperf_print(enum libperf_print_level level,
52 13 const char *fmt, va_list ap)
54 15 return vfprintf(stderr, fmt, ap);
57 23 int main(int argc, char **argv)
60 40 libperf_init(libperf_print);
63 It will setup the library and sets function for debug output from library.
65 The `libperf_print` callback will receive any message with its debug level,
70 enum libperf_print_level {
80 Once the setup is complete we start by defining cycles event using the `struct perf_event_attr`:
84 29 struct perf_event_attr attr = {
85 30 .type = PERF_TYPE_HARDWARE,
86 31 .config = PERF_COUNT_HW_CPU_CYCLES,
90 35 .sample_type = PERF_SAMPLE_IP|PERF_SAMPLE_TID|PERF_SAMPLE_CPU|PERF_SAMPLE_PERIOD,
94 Next step is to prepare CPUs map.
96 In this case we will monitor all the available CPUs:
100 42 cpus = perf_cpu_map__new(NULL);
102 44 fprintf(stderr, "failed to create cpus\n");
107 Now we create libperf's event list, which will serve as holder for the cycles event:
111 48 evlist = perf_evlist__new();
113 50 fprintf(stderr, "failed to create evlist\n");
118 We create libperf's event for the cycles attribute we defined earlier and add it to the list:
122 54 evsel = perf_evsel__new(&attr);
124 56 fprintf(stderr, "failed to create cycles\n");
128 60 perf_evlist__add(evlist, evsel);
131 Configure event list with the cpus map and open event:
135 62 perf_evlist__set_maps(evlist, cpus, NULL);
137 64 err = perf_evlist__open(evlist);
139 66 fprintf(stderr, "failed to open evlist\n");
144 Once the events list is open, we can create memory maps AKA perf ring buffers:
148 70 err = perf_evlist__mmap(evlist, 4);
150 72 fprintf(stderr, "failed to mmap evlist\n");
155 The event is created as disabled (note the `disabled = 1` assignment above),
156 so we need to enable the events list explicitly.
158 From this moment the cycles event is sampling.
160 We will sleep for 3 seconds while the ring buffers get data from all CPUs, then we disable the events list.
164 76 perf_evlist__enable(evlist);
166 78 perf_evlist__disable(evlist);
169 Following code walks through the ring buffers and reads stored events/samples:
173 80 perf_evlist__for_each_mmap(evlist, map, false) {
174 81 if (perf_mmap__read_init(map) < 0)
177 84 while ((event = perf_mmap__read_event(map)) != NULL) {
181 108 perf_mmap__consume(map);
183 110 perf_mmap__read_done(map);
188 Each sample needs to get parsed:
192 85 int cpu, pid, tid;
193 86 __u64 ip, period, *array;
196 89 array = event->sample.array;
207 100 cpu = u.val32[0];
212 105 fprintf(stdout, "cpu %3d, pid %6d, tid %6d, ip %20llx, period %20llu\n",
213 106 cpu, pid, tid, ip, period);
218 We close the whole events list (both events) and remove it together with the threads map:
223 114 perf_evlist__delete(evlist);
225 116 perf_cpu_map__put(cpus);
236 libperf is Free Software licensed under the GNU LGPL 2.1
240 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
244 libperf(3), libperf-counting(7)