Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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)