libperf-counting(7) 
 | 
=================== 
 | 
  
 | 
NAME 
 | 
---- 
 | 
libperf-counting - counting interface 
 | 
  
 | 
DESCRIPTION 
 | 
----------- 
 | 
The counting interface provides API to measure and get count for specific perf events. 
 | 
  
 | 
The following test tries to explain count on `counting.c` example. 
 | 
  
 | 
It is by no means complete guide to counting, but shows libperf basic API for counting. 
 | 
  
 | 
The `counting.c` comes with libperf package and can be compiled and run like: 
 | 
  
 | 
[source,bash] 
 | 
-- 
 | 
$ gcc -o counting counting.c -lperf 
 | 
$ sudo ./counting 
 | 
count 176792, enabled 176944, run 176944 
 | 
count 176242, enabled 176242, run 176242 
 | 
-- 
 | 
  
 | 
It requires root access, because of the `PERF_COUNT_SW_CPU_CLOCK` event, 
 | 
which is available only for root. 
 | 
  
 | 
The `counting.c` example monitors two events on the current process and displays 
 | 
their count, in a nutshell it: 
 | 
  
 | 
* creates events 
 | 
* adds them to the event list 
 | 
* opens and enables events through the event list 
 | 
* does some workload 
 | 
* disables events 
 | 
* reads and displays event counts 
 | 
* destroys the event list 
 | 
  
 | 
The first thing you need to do before using libperf is to call init function: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
  8 static int libperf_print(enum libperf_print_level level, 
 | 
  9                          const char *fmt, va_list ap) 
 | 
 10 { 
 | 
 11         return vfprintf(stderr, fmt, ap); 
 | 
 12 } 
 | 
  
 | 
 14 int main(int argc, char **argv) 
 | 
 15 { 
 | 
 ... 
 | 
 35         libperf_init(libperf_print); 
 | 
-- 
 | 
  
 | 
It will setup the library and sets function for debug output from library. 
 | 
  
 | 
The `libperf_print` callback will receive any message with its debug level, 
 | 
defined as: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
enum libperf_print_level { 
 | 
        LIBPERF_ERR, 
 | 
        LIBPERF_WARN, 
 | 
        LIBPERF_INFO, 
 | 
        LIBPERF_DEBUG, 
 | 
        LIBPERF_DEBUG2, 
 | 
        LIBPERF_DEBUG3, 
 | 
}; 
 | 
-- 
 | 
  
 | 
Once the setup is complete we start by defining specific events using the `struct perf_event_attr`. 
 | 
  
 | 
We create software events for cpu and task: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 20         struct perf_event_attr attr1 = { 
 | 
 21                 .type        = PERF_TYPE_SOFTWARE, 
 | 
 22                 .config      = PERF_COUNT_SW_CPU_CLOCK, 
 | 
 23                 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING, 
 | 
 24                 .disabled    = 1, 
 | 
 25         }; 
 | 
 26         struct perf_event_attr attr2 = { 
 | 
 27                 .type        = PERF_TYPE_SOFTWARE, 
 | 
 28                 .config      = PERF_COUNT_SW_TASK_CLOCK, 
 | 
 29                 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING, 
 | 
 30                 .disabled    = 1, 
 | 
 31         }; 
 | 
-- 
 | 
  
 | 
The `read_format` setup tells perf to include timing details together with each count. 
 | 
  
 | 
Next step is to prepare threads map. 
 | 
  
 | 
In this case we will monitor current process, so we create threads map with single pid (0): 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 37         threads = perf_thread_map__new_dummy(); 
 | 
 38         if (!threads) { 
 | 
 39                 fprintf(stderr, "failed to create threads\n"); 
 | 
 40                 return -1; 
 | 
 41         } 
 | 
 42 
 | 
 43         perf_thread_map__set_pid(threads, 0, 0); 
 | 
-- 
 | 
  
 | 
Now we create libperf's event list, which will serve as holder for the events we want: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 45         evlist = perf_evlist__new(); 
 | 
 46         if (!evlist) { 
 | 
 47                 fprintf(stderr, "failed to create evlist\n"); 
 | 
 48                 goto out_threads; 
 | 
 49         } 
 | 
-- 
 | 
  
 | 
We create libperf's events for the attributes we defined earlier and add them to the list: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 51         evsel = perf_evsel__new(&attr1); 
 | 
 52         if (!evsel) { 
 | 
 53                 fprintf(stderr, "failed to create evsel1\n"); 
 | 
 54                 goto out_evlist; 
 | 
 55         } 
 | 
 56 
 | 
 57         perf_evlist__add(evlist, evsel); 
 | 
 58 
 | 
 59         evsel = perf_evsel__new(&attr2); 
 | 
 60         if (!evsel) { 
 | 
 61                 fprintf(stderr, "failed to create evsel2\n"); 
 | 
 62                 goto out_evlist; 
 | 
 63         } 
 | 
 64 
 | 
 65         perf_evlist__add(evlist, evsel); 
 | 
-- 
 | 
  
 | 
Configure event list with the thread map and open events: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 67         perf_evlist__set_maps(evlist, NULL, threads); 
 | 
 68 
 | 
 69         err = perf_evlist__open(evlist); 
 | 
 70         if (err) { 
 | 
 71                 fprintf(stderr, "failed to open evsel\n"); 
 | 
 72                 goto out_evlist; 
 | 
 73         } 
 | 
-- 
 | 
  
 | 
Both events are created as disabled (note the `disabled = 1` assignment above), 
 | 
so we need to enable the whole list explicitly (both events). 
 | 
  
 | 
From this moment events are counting and we can do our workload. 
 | 
  
 | 
When we are done we disable the events list. 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 75         perf_evlist__enable(evlist); 
 | 
 76 
 | 
 77         while (count--); 
 | 
 78 
 | 
 79         perf_evlist__disable(evlist); 
 | 
-- 
 | 
  
 | 
Now we need to get the counts from events, following code iterates through the 
 | 
events list and read counts: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 81         perf_evlist__for_each_evsel(evlist, evsel) { 
 | 
 82                 perf_evsel__read(evsel, 0, 0, &counts); 
 | 
 83                 fprintf(stdout, "count %llu, enabled %llu, run %llu\n", 
 | 
 84                         counts.val, counts.ena, counts.run); 
 | 
 85         } 
 | 
-- 
 | 
  
 | 
And finally cleanup. 
 | 
  
 | 
We close the whole events list (both events) and remove it together with the threads map: 
 | 
  
 | 
[source,c] 
 | 
-- 
 | 
 87         perf_evlist__close(evlist); 
 | 
 88 
 | 
 89 out_evlist: 
 | 
 90         perf_evlist__delete(evlist); 
 | 
 91 out_threads: 
 | 
 92         perf_thread_map__put(threads); 
 | 
 93         return err; 
 | 
 94 } 
 | 
-- 
 | 
  
 | 
REPORTING BUGS 
 | 
-------------- 
 | 
Report bugs to <linux-perf-users@vger.kernel.org>. 
 | 
  
 | 
LICENSE 
 | 
------- 
 | 
libperf is Free Software licensed under the GNU LGPL 2.1 
 | 
  
 | 
RESOURCES 
 | 
--------- 
 | 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 
 | 
  
 | 
SEE ALSO 
 | 
-------- 
 | 
libperf(3), libperf-sampling(7) 
 |