libperf-counting - Man Page

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:

$ 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:

The first thing you need to do before using libperf is to call init function:

  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:

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:

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

 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:

 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:

 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:

 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​.

 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:

 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:

 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​[1]>​.

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)

Notes

1.

linux-perf-users@vger.kernel.org
mailto:linux-perf-users@vger.kernel.org

Info

10/09/2026 libperf Manual