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