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