1LIBPERF-COUNTING(7) libperf Manual LIBPERF-COUNTING(7)
2
3
4
6 libperf-counting - counting interface
7
9 The counting interface provides API to measure and get count for
10 specific perf events.
11
12 The following test tries to explain count on counting.c example.
13
14 It is by no means complete guide to counting, but shows libperf basic
15 API for counting.
16
17 The counting.c comes with libperf package and can be compiled and run
18 like:
19
20 $ gcc -o counting counting.c -lperf
21 $ sudo ./counting
22 count 176792, enabled 176944, run 176944
23 count 176242, enabled 176242, run 176242
24
25 It requires root access, because of the PERF_COUNT_SW_CPU_CLOCK event,
26 which is available only for root.
27
28 The counting.c example monitors two events on the current process and
29 displays their count, in a nutshell it:
30
31 • creates events
32
33 • adds them to the event list
34
35 • opens and enables events through the event list
36
37 • does some workload
38
39 • disables events
40
41 • reads and displays event counts
42
43 • destroys the event list
44
45 The first thing you need to do before using libperf is to call init
46 function:
47
48 8 static int libperf_print(enum libperf_print_level level,
49 9 const char *fmt, va_list ap)
50 10 {
51 11 return vfprintf(stderr, fmt, ap);
52 12 }
53
54 14 int main(int argc, char **argv)
55 15 {
56 ...
57 35 libperf_init(libperf_print);
58
59 It will setup the library and sets function for debug output from
60 library.
61
62 The libperf_print callback will receive any message with its debug
63 level, defined as:
64
65 enum libperf_print_level {
66 LIBPERF_ERR,
67 LIBPERF_WARN,
68 LIBPERF_INFO,
69 LIBPERF_DEBUG,
70 LIBPERF_DEBUG2,
71 LIBPERF_DEBUG3,
72 };
73
74 Once the setup is complete we start by defining specific events using
75 the struct perf_event_attr.
76
77 We create software events for cpu and task:
78
79 20 struct perf_event_attr attr1 = {
80 21 .type = PERF_TYPE_SOFTWARE,
81 22 .config = PERF_COUNT_SW_CPU_CLOCK,
82 23 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
83 24 .disabled = 1,
84 25 };
85 26 struct perf_event_attr attr2 = {
86 27 .type = PERF_TYPE_SOFTWARE,
87 28 .config = PERF_COUNT_SW_TASK_CLOCK,
88 29 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
89 30 .disabled = 1,
90 31 };
91
92 The read_format setup tells perf to include timing details together
93 with each count.
94
95 Next step is to prepare threads map.
96
97 In this case we will monitor current process, so we create threads map
98 with single pid (0):
99
100 37 threads = perf_thread_map__new_dummy();
101 38 if (!threads) {
102 39 fprintf(stderr, "failed to create threads\n");
103 40 return -1;
104 41 }
105 42
106 43 perf_thread_map__set_pid(threads, 0, 0);
107
108 Now we create libperf’s event list, which will serve as holder for the
109 events we want:
110
111 45 evlist = perf_evlist__new();
112 46 if (!evlist) {
113 47 fprintf(stderr, "failed to create evlist\n");
114 48 goto out_threads;
115 49 }
116
117 We create libperf’s events for the attributes we defined earlier and
118 add them to the list:
119
120 51 evsel = perf_evsel__new(&attr1);
121 52 if (!evsel) {
122 53 fprintf(stderr, "failed to create evsel1\n");
123 54 goto out_evlist;
124 55 }
125 56
126 57 perf_evlist__add(evlist, evsel);
127 58
128 59 evsel = perf_evsel__new(&attr2);
129 60 if (!evsel) {
130 61 fprintf(stderr, "failed to create evsel2\n");
131 62 goto out_evlist;
132 63 }
133 64
134 65 perf_evlist__add(evlist, evsel);
135
136 Configure event list with the thread map and open events:
137
138 67 perf_evlist__set_maps(evlist, NULL, threads);
139 68
140 69 err = perf_evlist__open(evlist);
141 70 if (err) {
142 71 fprintf(stderr, "failed to open evsel\n");
143 72 goto out_evlist;
144 73 }
145
146 Both events are created as disabled (note the disabled = 1 assignment
147 above), so we need to enable the whole list explicitly (both events).
148
149 From this moment events are counting and we can do our workload.
150
151 When we are done we disable the events list.
152
153 75 perf_evlist__enable(evlist);
154 76
155 77 while (count--);
156 78
157 79 perf_evlist__disable(evlist);
158
159 Now we need to get the counts from events, following code iterates
160 through the events list and read counts:
161
162 81 perf_evlist__for_each_evsel(evlist, evsel) {
163 82 perf_evsel__read(evsel, 0, 0, &counts);
164 83 fprintf(stdout, "count %llu, enabled %llu, run %llu\n",
165 84 counts.val, counts.ena, counts.run);
166 85 }
167
168 And finally cleanup.
169
170 We close the whole events list (both events) and remove it together
171 with the threads map:
172
173 87 perf_evlist__close(evlist);
174 88
175 89 out_evlist:
176 90 perf_evlist__delete(evlist);
177 91 out_threads:
178 92 perf_thread_map__put(threads);
179 93 return err;
180 94 }
181
183 Report bugs to <linux-perf-users@vger.kernel.org[1]>.
184
186 libperf is Free Software licensed under the GNU LGPL 2.1
187
189 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
190
192 libperf(3), libperf-sampling(7)
193
195 1. linux-perf-users@vger.kernel.org
196 mailto:linux-perf-users@vger.kernel.org
197
198
199
200libperf 11/22/2021 LIBPERF-COUNTING(7)