Loading...
Note: File does not exist in v3.1.
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)