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