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