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