| 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) |