Back to home page

OSCL-LXR

 
 

    


0001 libperf-counting(7)
0002 ===================
0003 
0004 NAME
0005 ----
0006 libperf-counting - counting interface
0007 
0008 DESCRIPTION
0009 -----------
0010 The counting interface provides API to measure and get count for specific perf events.
0011 
0012 The following test tries to explain count on `counting.c` example.
0013 
0014 It is by no means complete guide to counting, but shows libperf basic API for counting.
0015 
0016 The `counting.c` comes with libperf package and can be compiled and run like:
0017 
0018 [source,bash]
0019 --
0020 $ gcc -o counting counting.c -lperf
0021 $ sudo ./counting
0022 count 176792, enabled 176944, run 176944
0023 count 176242, enabled 176242, run 176242
0024 --
0025 
0026 It requires root access, because of the `PERF_COUNT_SW_CPU_CLOCK` event,
0027 which is available only for root.
0028 
0029 The `counting.c` example monitors two events on the current process and displays
0030 their count, in a nutshell it:
0031 
0032 * creates events
0033 * adds them to the event list
0034 * opens and enables events through the event list
0035 * does some workload
0036 * disables events
0037 * reads and displays event counts
0038 * destroys the event list
0039 
0040 The first thing you need to do before using libperf is to call init function:
0041 
0042 [source,c]
0043 --
0044   8 static int libperf_print(enum libperf_print_level level,
0045   9                          const char *fmt, va_list ap)
0046  10 {
0047  11         return vfprintf(stderr, fmt, ap);
0048  12 }
0049 
0050  14 int main(int argc, char **argv)
0051  15 {
0052  ...
0053  35         libperf_init(libperf_print);
0054 --
0055 
0056 It will setup the library and sets function for debug output from library.
0057 
0058 The `libperf_print` callback will receive any message with its debug level,
0059 defined as:
0060 
0061 [source,c]
0062 --
0063 enum libperf_print_level {
0064         LIBPERF_ERR,
0065         LIBPERF_WARN,
0066         LIBPERF_INFO,
0067         LIBPERF_DEBUG,
0068         LIBPERF_DEBUG2,
0069         LIBPERF_DEBUG3,
0070 };
0071 --
0072 
0073 Once the setup is complete we start by defining specific events using the `struct perf_event_attr`.
0074 
0075 We create software events for cpu and task:
0076 
0077 [source,c]
0078 --
0079  20         struct perf_event_attr attr1 = {
0080  21                 .type        = PERF_TYPE_SOFTWARE,
0081  22                 .config      = PERF_COUNT_SW_CPU_CLOCK,
0082  23                 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
0083  24                 .disabled    = 1,
0084  25         };
0085  26         struct perf_event_attr attr2 = {
0086  27                 .type        = PERF_TYPE_SOFTWARE,
0087  28                 .config      = PERF_COUNT_SW_TASK_CLOCK,
0088  29                 .read_format = PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING,
0089  30                 .disabled    = 1,
0090  31         };
0091 --
0092 
0093 The `read_format` setup tells perf to include timing details together with each count.
0094 
0095 Next step is to prepare threads map.
0096 
0097 In this case we will monitor current process, so we create threads map with single pid (0):
0098 
0099 [source,c]
0100 --
0101  37         threads = perf_thread_map__new_dummy();
0102  38         if (!threads) {
0103  39                 fprintf(stderr, "failed to create threads\n");
0104  40                 return -1;
0105  41         }
0106  42
0107  43         perf_thread_map__set_pid(threads, 0, 0);
0108 --
0109 
0110 Now we create libperf's event list, which will serve as holder for the events we want:
0111 
0112 [source,c]
0113 --
0114  45         evlist = perf_evlist__new();
0115  46         if (!evlist) {
0116  47                 fprintf(stderr, "failed to create evlist\n");
0117  48                 goto out_threads;
0118  49         }
0119 --
0120 
0121 We create libperf's events for the attributes we defined earlier and add them to the list:
0122 
0123 [source,c]
0124 --
0125  51         evsel = perf_evsel__new(&attr1);
0126  52         if (!evsel) {
0127  53                 fprintf(stderr, "failed to create evsel1\n");
0128  54                 goto out_evlist;
0129  55         }
0130  56
0131  57         perf_evlist__add(evlist, evsel);
0132  58
0133  59         evsel = perf_evsel__new(&attr2);
0134  60         if (!evsel) {
0135  61                 fprintf(stderr, "failed to create evsel2\n");
0136  62                 goto out_evlist;
0137  63         }
0138  64
0139  65         perf_evlist__add(evlist, evsel);
0140 --
0141 
0142 Configure event list with the thread map and open events:
0143 
0144 [source,c]
0145 --
0146  67         perf_evlist__set_maps(evlist, NULL, threads);
0147  68
0148  69         err = perf_evlist__open(evlist);
0149  70         if (err) {
0150  71                 fprintf(stderr, "failed to open evsel\n");
0151  72                 goto out_evlist;
0152  73         }
0153 --
0154 
0155 Both events are created as disabled (note the `disabled = 1` assignment above),
0156 so we need to enable the whole list explicitly (both events).
0157 
0158 From this moment events are counting and we can do our workload.
0159 
0160 When we are done we disable the events list.
0161 
0162 [source,c]
0163 --
0164  75         perf_evlist__enable(evlist);
0165  76
0166  77         while (count--);
0167  78
0168  79         perf_evlist__disable(evlist);
0169 --
0170 
0171 Now we need to get the counts from events, following code iterates through the
0172 events list and read counts:
0173 
0174 [source,c]
0175 --
0176  81         perf_evlist__for_each_evsel(evlist, evsel) {
0177  82                 perf_evsel__read(evsel, 0, 0, &counts);
0178  83                 fprintf(stdout, "count %llu, enabled %llu, run %llu\n",
0179  84                         counts.val, counts.ena, counts.run);
0180  85         }
0181 --
0182 
0183 And finally cleanup.
0184 
0185 We close the whole events list (both events) and remove it together with the threads map:
0186 
0187 [source,c]
0188 --
0189  87         perf_evlist__close(evlist);
0190  88
0191  89 out_evlist:
0192  90         perf_evlist__delete(evlist);
0193  91 out_threads:
0194  92         perf_thread_map__put(threads);
0195  93         return err;
0196  94 }
0197 --
0198 
0199 REPORTING BUGS
0200 --------------
0201 Report bugs to <linux-perf-users@vger.kernel.org>.
0202 
0203 LICENSE
0204 -------
0205 libperf is Free Software licensed under the GNU LGPL 2.1
0206 
0207 RESOURCES
0208 ---------
0209 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
0210 
0211 SEE ALSO
0212 --------
0213 libperf(3), libperf-sampling(7)