perf_plugin.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "libnetdata/libnetdata.h"
  3. #include "libnetdata/required_dummies.h"
  4. #include <linux/perf_event.h>
  5. #define PLUGIN_PERF_NAME "perf.plugin"
  6. // Hardware counters
  7. #define NETDATA_CHART_PRIO_PERF_CPU_CYCLES 8800
  8. #define NETDATA_CHART_PRIO_PERF_INSTRUCTIONS 8801
  9. #define NETDATA_CHART_PRIO_PERF_IPC 8802
  10. #define NETDATA_CHART_PRIO_PERF_BRANCH_INSTRUCTIONS 8803
  11. #define NETDATA_CHART_PRIO_PERF_CACHE 8804
  12. #define NETDATA_CHART_PRIO_PERF_BUS_CYCLES 8805
  13. #define NETDATA_CHART_PRIO_PERF_FRONT_BACK_CYCLES 8806
  14. // Software counters
  15. #define NETDATA_CHART_PRIO_PERF_MIGRATIONS 8810
  16. #define NETDATA_CHART_PRIO_PERF_ALIGNMENT 8811
  17. #define NETDATA_CHART_PRIO_PERF_EMULATION 8812
  18. // Hardware cache counters
  19. #define NETDATA_CHART_PRIO_PERF_L1D 8820
  20. #define NETDATA_CHART_PRIO_PERF_L1D_PREFETCH 8821
  21. #define NETDATA_CHART_PRIO_PERF_L1I 8822
  22. #define NETDATA_CHART_PRIO_PERF_LL 8823
  23. #define NETDATA_CHART_PRIO_PERF_DTLB 8824
  24. #define NETDATA_CHART_PRIO_PERF_ITLB 8825
  25. #define NETDATA_CHART_PRIO_PERF_PBU 8826
  26. #define RRD_TYPE_PERF "perf"
  27. #define RRD_FAMILY_HW "hardware"
  28. #define RRD_FAMILY_SW "software"
  29. #define RRD_FAMILY_CACHE "cache"
  30. #define NO_FD -1
  31. #define ALL_PIDS -1
  32. #define RUNNING_THRESHOLD 100
  33. static int debug = 0;
  34. static int update_every = 1;
  35. static int freq = 0;
  36. typedef enum perf_event_id {
  37. // Hardware counters
  38. EV_ID_CPU_CYCLES,
  39. EV_ID_INSTRUCTIONS,
  40. EV_ID_CACHE_REFERENCES,
  41. EV_ID_CACHE_MISSES,
  42. EV_ID_BRANCH_INSTRUCTIONS,
  43. EV_ID_BRANCH_MISSES,
  44. EV_ID_BUS_CYCLES,
  45. EV_ID_STALLED_CYCLES_FRONTEND,
  46. EV_ID_STALLED_CYCLES_BACKEND,
  47. EV_ID_REF_CPU_CYCLES,
  48. // Software counters
  49. // EV_ID_CPU_CLOCK,
  50. // EV_ID_TASK_CLOCK,
  51. // EV_ID_PAGE_FAULTS,
  52. // EV_ID_CONTEXT_SWITCHES,
  53. EV_ID_CPU_MIGRATIONS,
  54. // EV_ID_PAGE_FAULTS_MIN,
  55. // EV_ID_PAGE_FAULTS_MAJ,
  56. EV_ID_ALIGNMENT_FAULTS,
  57. EV_ID_EMULATION_FAULTS,
  58. // Hardware cache counters
  59. EV_ID_L1D_READ_ACCESS,
  60. EV_ID_L1D_READ_MISS,
  61. EV_ID_L1D_WRITE_ACCESS,
  62. EV_ID_L1D_WRITE_MISS,
  63. EV_ID_L1D_PREFETCH_ACCESS,
  64. EV_ID_L1I_READ_ACCESS,
  65. EV_ID_L1I_READ_MISS,
  66. EV_ID_LL_READ_ACCESS,
  67. EV_ID_LL_READ_MISS,
  68. EV_ID_LL_WRITE_ACCESS,
  69. EV_ID_LL_WRITE_MISS,
  70. EV_ID_DTLB_READ_ACCESS,
  71. EV_ID_DTLB_READ_MISS,
  72. EV_ID_DTLB_WRITE_ACCESS,
  73. EV_ID_DTLB_WRITE_MISS,
  74. EV_ID_ITLB_READ_ACCESS,
  75. EV_ID_ITLB_READ_MISS,
  76. EV_ID_PBU_READ_ACCESS,
  77. EV_ID_END
  78. } perf_event_id_t;
  79. enum perf_event_group {
  80. EV_GROUP_CYCLES,
  81. EV_GROUP_INSTRUCTIONS_AND_CACHE,
  82. EV_GROUP_SOFTWARE,
  83. EV_GROUP_CACHE_L1D,
  84. EV_GROUP_CACHE_L1I_LL_DTLB,
  85. EV_GROUP_CACHE_ITLB_BPU,
  86. EV_GROUP_NUM
  87. };
  88. static int number_of_cpus;
  89. static int *group_leader_fds[EV_GROUP_NUM];
  90. static struct perf_event {
  91. perf_event_id_t id;
  92. int type;
  93. int config;
  94. int **group_leader_fd;
  95. int *fd;
  96. int disabled;
  97. int updated;
  98. uint64_t value;
  99. uint64_t *prev_value;
  100. uint64_t *prev_time_enabled;
  101. uint64_t *prev_time_running;
  102. } perf_events[] = {
  103. // Hardware counters
  104. {EV_ID_CPU_CYCLES, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES, &group_leader_fds[EV_GROUP_CYCLES], NULL, 1, 0, 0, NULL, NULL, NULL},
  105. {EV_ID_INSTRUCTIONS, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS, &group_leader_fds[EV_GROUP_INSTRUCTIONS_AND_CACHE], NULL, 1, 0, 0, NULL, NULL, NULL},
  106. {EV_ID_CACHE_REFERENCES, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES, &group_leader_fds[EV_GROUP_INSTRUCTIONS_AND_CACHE], NULL, 1, 0, 0, NULL, NULL, NULL},
  107. {EV_ID_CACHE_MISSES, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES, &group_leader_fds[EV_GROUP_INSTRUCTIONS_AND_CACHE], NULL, 1, 0, 0, NULL, NULL, NULL},
  108. {EV_ID_BRANCH_INSTRUCTIONS, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS, &group_leader_fds[EV_GROUP_INSTRUCTIONS_AND_CACHE], NULL, 1, 0, 0, NULL, NULL, NULL},
  109. {EV_ID_BRANCH_MISSES, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES, &group_leader_fds[EV_GROUP_INSTRUCTIONS_AND_CACHE], NULL, 1, 0, 0, NULL, NULL, NULL},
  110. {EV_ID_BUS_CYCLES, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES, &group_leader_fds[EV_GROUP_CYCLES], NULL, 1, 0, 0, NULL, NULL, NULL},
  111. {EV_ID_STALLED_CYCLES_FRONTEND, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND, &group_leader_fds[EV_GROUP_CYCLES], NULL, 1, 0, 0, NULL, NULL, NULL},
  112. {EV_ID_STALLED_CYCLES_BACKEND, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND, &group_leader_fds[EV_GROUP_CYCLES], NULL, 1, 0, 0, NULL, NULL, NULL},
  113. {EV_ID_REF_CPU_CYCLES, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES, &group_leader_fds[EV_GROUP_CYCLES], NULL, 1, 0, 0, NULL, NULL, NULL},
  114. // Software counters
  115. // {EV_ID_CPU_CLOCK, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  116. // {EV_ID_TASK_CLOCK, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  117. // {EV_ID_PAGE_FAULTS, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  118. // {EV_ID_CONTEXT_SWITCHES, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  119. {EV_ID_CPU_MIGRATIONS, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  120. // {EV_ID_PAGE_FAULTS_MIN, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  121. // {EV_ID_PAGE_FAULTS_MAJ, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  122. {EV_ID_ALIGNMENT_FAULTS, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  123. {EV_ID_EMULATION_FAULTS, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS, &group_leader_fds[EV_GROUP_SOFTWARE], NULL, 1, 0, 0, NULL, NULL, NULL},
  124. // Hardware cache counters
  125. {
  126. EV_ID_L1D_READ_ACCESS, PERF_TYPE_HW_CACHE,
  127. (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  128. &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
  129. }, {
  130. EV_ID_L1D_READ_MISS, PERF_TYPE_HW_CACHE,
  131. (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  132. &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
  133. }, {
  134. EV_ID_L1D_WRITE_ACCESS, PERF_TYPE_HW_CACHE,
  135. (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  136. &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
  137. }, {
  138. EV_ID_L1D_WRITE_MISS, PERF_TYPE_HW_CACHE,
  139. (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  140. &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
  141. }, {
  142. EV_ID_L1D_PREFETCH_ACCESS, PERF_TYPE_HW_CACHE,
  143. (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  144. &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
  145. },
  146. {
  147. EV_ID_L1I_READ_ACCESS, PERF_TYPE_HW_CACHE,
  148. (PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  149. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  150. }, {
  151. EV_ID_L1I_READ_MISS, PERF_TYPE_HW_CACHE,
  152. (PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  153. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  154. },
  155. {
  156. EV_ID_LL_READ_ACCESS, PERF_TYPE_HW_CACHE,
  157. (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  158. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  159. }, {
  160. EV_ID_LL_READ_MISS, PERF_TYPE_HW_CACHE,
  161. (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  162. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  163. }, {
  164. EV_ID_LL_WRITE_ACCESS, PERF_TYPE_HW_CACHE,
  165. (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  166. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  167. }, {
  168. EV_ID_LL_WRITE_MISS, PERF_TYPE_HW_CACHE,
  169. (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  170. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  171. },
  172. {
  173. EV_ID_DTLB_READ_ACCESS, PERF_TYPE_HW_CACHE,
  174. (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  175. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  176. }, {
  177. EV_ID_DTLB_READ_MISS, PERF_TYPE_HW_CACHE,
  178. (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  179. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  180. }, {
  181. EV_ID_DTLB_WRITE_ACCESS, PERF_TYPE_HW_CACHE,
  182. (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  183. &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
  184. }, {
  185. EV_ID_DTLB_WRITE_MISS, PERF_TYPE_HW_CACHE,
  186. (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  187. &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
  188. },
  189. {
  190. EV_ID_ITLB_READ_ACCESS, PERF_TYPE_HW_CACHE,
  191. (PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  192. &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
  193. }, {
  194. EV_ID_ITLB_READ_MISS, PERF_TYPE_HW_CACHE,
  195. (PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
  196. &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
  197. },
  198. {
  199. EV_ID_PBU_READ_ACCESS, PERF_TYPE_HW_CACHE,
  200. (PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
  201. &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
  202. },
  203. {EV_ID_END, 0, 0, NULL, NULL, 0, 0, 0, NULL, NULL, NULL}
  204. };
  205. static int perf_init() {
  206. int cpu, group;
  207. struct perf_event_attr perf_event_attr;
  208. struct perf_event *current_event = NULL;
  209. unsigned long flags = 0;
  210. number_of_cpus = (int)get_system_cpus();
  211. // initialize all perf event file descriptors
  212. for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
  213. current_event->fd = mallocz(number_of_cpus * sizeof(int));
  214. memset(current_event->fd, NO_FD, number_of_cpus * sizeof(int));
  215. current_event->prev_value = mallocz(number_of_cpus * sizeof(uint64_t));
  216. memset(current_event->prev_value, 0, number_of_cpus * sizeof(uint64_t));
  217. current_event->prev_time_enabled = mallocz(number_of_cpus * sizeof(uint64_t));
  218. memset(current_event->prev_time_enabled, 0, number_of_cpus * sizeof(uint64_t));
  219. current_event->prev_time_running = mallocz(number_of_cpus * sizeof(uint64_t));
  220. memset(current_event->prev_time_running, 0, number_of_cpus * sizeof(uint64_t));
  221. }
  222. for(group = 0; group < EV_GROUP_NUM; group++) {
  223. group_leader_fds[group] = mallocz(number_of_cpus * sizeof(int));
  224. memset(group_leader_fds[group], NO_FD, number_of_cpus * sizeof(int));
  225. }
  226. memset(&perf_event_attr, 0, sizeof(perf_event_attr));
  227. for(cpu = 0; cpu < number_of_cpus; cpu++) {
  228. for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
  229. if(unlikely(current_event->disabled)) continue;
  230. perf_event_attr.type = current_event->type;
  231. perf_event_attr.config = current_event->config;
  232. perf_event_attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
  233. int fd, group_leader_fd = *(*current_event->group_leader_fd + cpu);
  234. fd = syscall(
  235. __NR_perf_event_open,
  236. &perf_event_attr,
  237. ALL_PIDS,
  238. cpu,
  239. group_leader_fd,
  240. flags
  241. );
  242. if(unlikely(group_leader_fd == NO_FD)) group_leader_fd = fd;
  243. if(unlikely(fd < 0)) {
  244. switch errno {
  245. case EACCES:
  246. collector_error("Cannot access to the PMU: Permission denied");
  247. break;
  248. case EBUSY:
  249. collector_error("Another event already has exclusive access to the PMU");
  250. break;
  251. default:
  252. collector_error("Cannot open perf event");
  253. }
  254. collector_error("Disabling event %u", current_event->id);
  255. current_event->disabled = 1;
  256. }
  257. *(current_event->fd + cpu) = fd;
  258. *(*current_event->group_leader_fd + cpu) = group_leader_fd;
  259. if(unlikely(debug)) fprintf(stderr, "perf.plugin: event id = %u, cpu = %d, fd = %d, leader_fd = %d\n", current_event->id, cpu, fd, group_leader_fd);
  260. }
  261. }
  262. return 0;
  263. }
  264. static void perf_free(void) {
  265. int cpu, group;
  266. struct perf_event *current_event = NULL;
  267. for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
  268. for(cpu = 0; cpu < number_of_cpus; cpu++)
  269. if(*(current_event->fd + cpu) != NO_FD) close(*(current_event->fd + cpu));
  270. free(current_event->fd);
  271. free(current_event->prev_value);
  272. free(current_event->prev_time_enabled);
  273. free(current_event->prev_time_running);
  274. }
  275. for(group = 0; group < EV_GROUP_NUM; group++)
  276. free(group_leader_fds[group]);
  277. }
  278. static void reenable_events() {
  279. int group, cpu;
  280. for(group = 0; group < EV_GROUP_NUM; group++) {
  281. for(cpu = 0; cpu < number_of_cpus; cpu++) {
  282. int current_fd = *(group_leader_fds[group] + cpu);
  283. if(unlikely(current_fd == NO_FD)) continue;
  284. if(ioctl(current_fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1
  285. || ioctl(current_fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1)
  286. {
  287. collector_error("Cannot reenable event group");
  288. }
  289. }
  290. }
  291. }
  292. static int perf_collect() {
  293. int cpu;
  294. struct perf_event *current_event = NULL;
  295. static uint64_t prev_cpu_cycles_value = 0;
  296. struct {
  297. uint64_t value;
  298. uint64_t time_enabled;
  299. uint64_t time_running;
  300. } read_result;
  301. for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
  302. current_event->updated = 0;
  303. current_event->value = 0;
  304. if(unlikely(current_event->disabled)) continue;
  305. for(cpu = 0; cpu < number_of_cpus; cpu++) {
  306. ssize_t read_size = read(current_event->fd[cpu], &read_result, sizeof(read_result));
  307. if(likely(read_size == sizeof(read_result))) {
  308. if (likely(read_result.time_running
  309. && read_result.time_running != *(current_event->prev_time_running + cpu)
  310. && (read_result.time_enabled / read_result.time_running < RUNNING_THRESHOLD))) {
  311. current_event->value += (read_result.value - *(current_event->prev_value + cpu)) \
  312. * (read_result.time_enabled - *(current_event->prev_time_enabled + cpu)) \
  313. / (read_result.time_running - *(current_event->prev_time_running + cpu));
  314. }
  315. *(current_event->prev_value + cpu) = read_result.value;
  316. *(current_event->prev_time_enabled + cpu) = read_result.time_enabled;
  317. *(current_event->prev_time_running + cpu) = read_result.time_running;
  318. current_event->updated = 1;
  319. }
  320. else {
  321. collector_error("Cannot update value for event %u", current_event->id);
  322. return 1;
  323. }
  324. }
  325. if(unlikely(debug)) fprintf(stderr, "perf.plugin: successfully read event id = %u, value = %"PRIu64"\n", current_event->id, current_event->value);
  326. }
  327. if(unlikely(perf_events[EV_ID_CPU_CYCLES].value == prev_cpu_cycles_value))
  328. reenable_events();
  329. prev_cpu_cycles_value = perf_events[EV_ID_CPU_CYCLES].value;
  330. return 0;
  331. }
  332. static void perf_send_metrics() {
  333. static int // Hardware counters
  334. cpu_cycles_chart_generated = 0,
  335. instructions_chart_generated = 0,
  336. ipc_chart_generated = 0,
  337. branch_chart_generated = 0,
  338. cache_chart_generated = 0,
  339. bus_cycles_chart_generated = 0,
  340. stalled_cycles_chart_generated = 0,
  341. // Software counters
  342. migrations_chart_generated = 0,
  343. alignment_chart_generated = 0,
  344. emulation_chart_generated = 0,
  345. // Hardware cache counters
  346. L1D_chart_generated = 0,
  347. L1D_prefetch_chart_generated = 0,
  348. L1I_chart_generated = 0,
  349. LL_chart_generated = 0,
  350. DTLB_chart_generated = 0,
  351. ITLB_chart_generated = 0,
  352. PBU_chart_generated = 0;
  353. // ------------------------------------------------------------------------
  354. if(likely(perf_events[EV_ID_CPU_CYCLES].updated || perf_events[EV_ID_REF_CPU_CYCLES].updated)) {
  355. if(unlikely(!cpu_cycles_chart_generated)) {
  356. cpu_cycles_chart_generated = 1;
  357. printf("CHART %s.%s '' 'CPU cycles' 'cycles/s' %s '' line %d %d '' %s\n"
  358. , RRD_TYPE_PERF
  359. , "cpu_cycles"
  360. , RRD_FAMILY_HW
  361. , NETDATA_CHART_PRIO_PERF_CPU_CYCLES
  362. , update_every
  363. , PLUGIN_PERF_NAME
  364. );
  365. printf("DIMENSION %s '' absolute 1 1\n", "cpu");
  366. printf("DIMENSION %s '' absolute 1 1\n", "ref_cpu");
  367. }
  368. printf(
  369. "BEGIN %s.%s\n"
  370. , RRD_TYPE_PERF
  371. , "cpu_cycles"
  372. );
  373. if(likely(perf_events[EV_ID_CPU_CYCLES].updated)) {
  374. printf(
  375. "SET %s = %lld\n"
  376. , "cpu"
  377. , (collected_number) perf_events[EV_ID_CPU_CYCLES].value
  378. );
  379. }
  380. if(likely(perf_events[EV_ID_REF_CPU_CYCLES].updated)) {
  381. printf(
  382. "SET %s = %lld\n"
  383. , "ref_cpu"
  384. , (collected_number) perf_events[EV_ID_REF_CPU_CYCLES].value
  385. );
  386. }
  387. printf("END\n");
  388. }
  389. // ------------------------------------------------------------------------
  390. if(likely(perf_events[EV_ID_INSTRUCTIONS].updated)) {
  391. if(unlikely(!instructions_chart_generated)) {
  392. instructions_chart_generated = 1;
  393. printf("CHART %s.%s '' 'Instructions' 'instructions/s' %s '' line %d %d '' %s\n"
  394. , RRD_TYPE_PERF
  395. , "instructions"
  396. , RRD_FAMILY_HW
  397. , NETDATA_CHART_PRIO_PERF_INSTRUCTIONS
  398. , update_every
  399. , PLUGIN_PERF_NAME
  400. );
  401. printf("DIMENSION %s '' absolute 1 1\n", "instructions");
  402. }
  403. printf(
  404. "BEGIN %s.%s\n"
  405. , RRD_TYPE_PERF
  406. , "instructions"
  407. );
  408. printf(
  409. "SET %s = %lld\n"
  410. , "instructions"
  411. , (collected_number) perf_events[EV_ID_INSTRUCTIONS].value
  412. );
  413. printf("END\n");
  414. }
  415. // ------------------------------------------------------------------------
  416. if(likely(perf_events[EV_ID_INSTRUCTIONS].updated) && likely(perf_events[EV_ID_CPU_CYCLES].updated)) {
  417. if(unlikely(!ipc_chart_generated)) {
  418. ipc_chart_generated = 1;
  419. printf("CHART %s.%s '' '%s' 'instructions/cycle' %s '' line %d %d '' %s\n"
  420. , RRD_TYPE_PERF
  421. , "instructions_per_cycle"
  422. , "Instructions per Cycle(IPC)"
  423. , RRD_FAMILY_HW
  424. , NETDATA_CHART_PRIO_PERF_IPC
  425. , update_every
  426. , PLUGIN_PERF_NAME
  427. );
  428. printf("DIMENSION %s '' absolute 1 100\n", "ipc");
  429. }
  430. printf("BEGIN %s.%s\n"
  431. , RRD_TYPE_PERF
  432. , "instructions_per_cycle"
  433. );
  434. NETDATA_DOUBLE result = ((NETDATA_DOUBLE)perf_events[EV_ID_INSTRUCTIONS].value /
  435. (NETDATA_DOUBLE)perf_events[EV_ID_CPU_CYCLES].value) * 100.0;
  436. printf("SET %s = %lld\n"
  437. , "ipc"
  438. , (collected_number) result
  439. );
  440. printf("END\n");
  441. }
  442. // ------------------------------------------------------------------------
  443. if(likely(perf_events[EV_ID_BRANCH_INSTRUCTIONS].updated || perf_events[EV_ID_BRANCH_MISSES].updated)) {
  444. if(unlikely(!branch_chart_generated)) {
  445. branch_chart_generated = 1;
  446. printf("CHART %s.%s '' 'Branch instructions' 'instructions/s' %s '' line %d %d '' %s\n"
  447. , RRD_TYPE_PERF
  448. , "branch_instructions"
  449. , RRD_FAMILY_HW
  450. , NETDATA_CHART_PRIO_PERF_BRANCH_INSTRUCTIONS
  451. , update_every
  452. , PLUGIN_PERF_NAME
  453. );
  454. printf("DIMENSION %s '' absolute 1 1\n", "instructions");
  455. printf("DIMENSION %s '' absolute 1 1\n", "misses");
  456. }
  457. printf(
  458. "BEGIN %s.%s\n"
  459. , RRD_TYPE_PERF
  460. , "branch_instructions"
  461. );
  462. if(likely(perf_events[EV_ID_BRANCH_INSTRUCTIONS].updated)) {
  463. printf(
  464. "SET %s = %lld\n"
  465. , "instructions"
  466. , (collected_number) perf_events[EV_ID_BRANCH_INSTRUCTIONS].value
  467. );
  468. }
  469. if(likely(perf_events[EV_ID_BRANCH_MISSES].updated)) {
  470. printf(
  471. "SET %s = %lld\n"
  472. , "misses"
  473. , (collected_number) perf_events[EV_ID_BRANCH_MISSES].value
  474. );
  475. }
  476. printf("END\n");
  477. }
  478. // ------------------------------------------------------------------------
  479. if(likely(perf_events[EV_ID_CACHE_REFERENCES].updated || perf_events[EV_ID_CACHE_MISSES].updated)) {
  480. if(unlikely(!cache_chart_generated)) {
  481. cache_chart_generated = 1;
  482. printf("CHART %s.%s '' 'Cache operations' 'operations/s' %s '' line %d %d '' %s\n"
  483. , RRD_TYPE_PERF
  484. , "cache"
  485. , RRD_FAMILY_HW
  486. , NETDATA_CHART_PRIO_PERF_CACHE
  487. , update_every
  488. , PLUGIN_PERF_NAME
  489. );
  490. printf("DIMENSION %s '' absolute 1 1\n", "references");
  491. printf("DIMENSION %s '' absolute 1 1\n", "misses");
  492. }
  493. printf(
  494. "BEGIN %s.%s\n"
  495. , RRD_TYPE_PERF
  496. , "cache"
  497. );
  498. if(likely(perf_events[EV_ID_CACHE_REFERENCES].updated)) {
  499. printf(
  500. "SET %s = %lld\n"
  501. , "references"
  502. , (collected_number) perf_events[EV_ID_CACHE_REFERENCES].value
  503. );
  504. }
  505. if(likely(perf_events[EV_ID_CACHE_MISSES].updated)) {
  506. printf(
  507. "SET %s = %lld\n"
  508. , "misses"
  509. , (collected_number) perf_events[EV_ID_CACHE_MISSES].value
  510. );
  511. }
  512. printf("END\n");
  513. }
  514. // ------------------------------------------------------------------------
  515. if(likely(perf_events[EV_ID_BUS_CYCLES].updated)) {
  516. if(unlikely(!bus_cycles_chart_generated)) {
  517. bus_cycles_chart_generated = 1;
  518. printf("CHART %s.%s '' 'Bus cycles' 'cycles/s' %s '' line %d %d '' %s\n"
  519. , RRD_TYPE_PERF
  520. , "bus_cycles"
  521. , RRD_FAMILY_HW
  522. , NETDATA_CHART_PRIO_PERF_BUS_CYCLES
  523. , update_every
  524. , PLUGIN_PERF_NAME
  525. );
  526. printf("DIMENSION %s '' absolute 1 1\n", "bus");
  527. }
  528. printf(
  529. "BEGIN %s.%s\n"
  530. , RRD_TYPE_PERF
  531. , "bus_cycles"
  532. );
  533. printf(
  534. "SET %s = %lld\n"
  535. , "bus"
  536. , (collected_number) perf_events[EV_ID_BUS_CYCLES].value
  537. );
  538. printf("END\n");
  539. }
  540. // ------------------------------------------------------------------------
  541. if(likely(perf_events[EV_ID_STALLED_CYCLES_FRONTEND].updated || perf_events[EV_ID_STALLED_CYCLES_BACKEND].updated)) {
  542. if(unlikely(!stalled_cycles_chart_generated)) {
  543. stalled_cycles_chart_generated = 1;
  544. printf("CHART %s.%s '' 'Stalled frontend and backend cycles' 'cycles/s' %s '' line %d %d '' %s\n"
  545. , RRD_TYPE_PERF
  546. , "stalled_cycles"
  547. , RRD_FAMILY_HW
  548. , NETDATA_CHART_PRIO_PERF_FRONT_BACK_CYCLES
  549. , update_every
  550. , PLUGIN_PERF_NAME
  551. );
  552. printf("DIMENSION %s '' absolute 1 1\n", "frontend");
  553. printf("DIMENSION %s '' absolute 1 1\n", "backend");
  554. }
  555. printf(
  556. "BEGIN %s.%s\n"
  557. , RRD_TYPE_PERF
  558. , "stalled_cycles"
  559. );
  560. if(likely(perf_events[EV_ID_STALLED_CYCLES_FRONTEND].updated)) {
  561. printf(
  562. "SET %s = %lld\n"
  563. , "frontend"
  564. , (collected_number) perf_events[EV_ID_STALLED_CYCLES_FRONTEND].value
  565. );
  566. }
  567. if(likely(perf_events[EV_ID_STALLED_CYCLES_BACKEND].updated)) {
  568. printf(
  569. "SET %s = %lld\n"
  570. , "backend"
  571. , (collected_number) perf_events[EV_ID_STALLED_CYCLES_BACKEND].value
  572. );
  573. }
  574. printf("END\n");
  575. }
  576. // ------------------------------------------------------------------------
  577. if(likely(perf_events[EV_ID_CPU_MIGRATIONS].updated)) {
  578. if(unlikely(!migrations_chart_generated)) {
  579. migrations_chart_generated = 1;
  580. printf("CHART %s.%s '' 'CPU migrations' 'migrations' %s '' line %d %d '' %s\n"
  581. , RRD_TYPE_PERF
  582. , "migrations"
  583. , RRD_FAMILY_SW
  584. , NETDATA_CHART_PRIO_PERF_MIGRATIONS
  585. , update_every
  586. , PLUGIN_PERF_NAME
  587. );
  588. printf("DIMENSION %s '' absolute 1 1\n", "migrations");
  589. }
  590. printf(
  591. "BEGIN %s.%s\n"
  592. , RRD_TYPE_PERF
  593. , "migrations"
  594. );
  595. printf(
  596. "SET %s = %lld\n"
  597. , "migrations"
  598. , (collected_number) perf_events[EV_ID_CPU_MIGRATIONS].value
  599. );
  600. printf("END\n");
  601. }
  602. // ------------------------------------------------------------------------
  603. if(likely(perf_events[EV_ID_ALIGNMENT_FAULTS].updated)) {
  604. if(unlikely(!alignment_chart_generated)) {
  605. alignment_chart_generated = 1;
  606. printf("CHART %s.%s '' 'Alignment faults' 'faults' %s '' line %d %d '' %s\n"
  607. , RRD_TYPE_PERF
  608. , "alignment_faults"
  609. , RRD_FAMILY_SW
  610. , NETDATA_CHART_PRIO_PERF_ALIGNMENT
  611. , update_every
  612. , PLUGIN_PERF_NAME
  613. );
  614. printf("DIMENSION %s '' absolute 1 1\n", "faults");
  615. }
  616. printf(
  617. "BEGIN %s.%s\n"
  618. , RRD_TYPE_PERF
  619. , "alignment_faults"
  620. );
  621. printf(
  622. "SET %s = %lld\n"
  623. , "faults"
  624. , (collected_number) perf_events[EV_ID_ALIGNMENT_FAULTS].value
  625. );
  626. printf("END\n");
  627. }
  628. // ------------------------------------------------------------------------
  629. if(likely(perf_events[EV_ID_EMULATION_FAULTS].updated)) {
  630. if(unlikely(!emulation_chart_generated)) {
  631. emulation_chart_generated = 1;
  632. printf("CHART %s.%s '' 'Emulation faults' 'faults' %s '' line %d %d '' %s\n"
  633. , RRD_TYPE_PERF
  634. , "emulation_faults"
  635. , RRD_FAMILY_SW
  636. , NETDATA_CHART_PRIO_PERF_EMULATION
  637. , update_every
  638. , PLUGIN_PERF_NAME
  639. );
  640. printf("DIMENSION %s '' absolute 1 1\n", "faults");
  641. }
  642. printf(
  643. "BEGIN %s.%s\n"
  644. , RRD_TYPE_PERF
  645. , "emulation_faults"
  646. );
  647. printf(
  648. "SET %s = %lld\n"
  649. , "faults"
  650. , (collected_number) perf_events[EV_ID_EMULATION_FAULTS].value
  651. );
  652. printf("END\n");
  653. }
  654. // ------------------------------------------------------------------------
  655. if(likely(perf_events[EV_ID_L1D_READ_ACCESS].updated || perf_events[EV_ID_L1D_READ_MISS].updated
  656. || perf_events[EV_ID_L1D_WRITE_ACCESS].updated || perf_events[EV_ID_L1D_WRITE_MISS].updated)) {
  657. if(unlikely(!L1D_chart_generated)) {
  658. L1D_chart_generated = 1;
  659. printf("CHART %s.%s '' 'L1D cache operations' 'events/s' %s '' line %d %d '' %s\n"
  660. , RRD_TYPE_PERF
  661. , "l1d_cache"
  662. , RRD_FAMILY_CACHE
  663. , NETDATA_CHART_PRIO_PERF_L1D
  664. , update_every
  665. , PLUGIN_PERF_NAME
  666. );
  667. printf("DIMENSION %s '' absolute 1 1\n", "read_access");
  668. printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
  669. printf("DIMENSION %s '' absolute -1 1\n", "write_access");
  670. printf("DIMENSION %s '' absolute -1 1\n", "write_misses");
  671. }
  672. printf(
  673. "BEGIN %s.%s\n"
  674. , RRD_TYPE_PERF
  675. , "l1d_cache"
  676. );
  677. if(likely(perf_events[EV_ID_L1D_READ_ACCESS].updated)) {
  678. printf(
  679. "SET %s = %lld\n"
  680. , "read_access"
  681. , (collected_number) perf_events[EV_ID_L1D_READ_ACCESS].value
  682. );
  683. }
  684. if(likely(perf_events[EV_ID_L1D_READ_MISS].updated)) {
  685. printf(
  686. "SET %s = %lld\n"
  687. , "read_misses"
  688. , (collected_number) perf_events[EV_ID_L1D_READ_MISS].value
  689. );
  690. }
  691. if(likely(perf_events[EV_ID_L1D_WRITE_ACCESS].updated)) {
  692. printf(
  693. "SET %s = %lld\n"
  694. , "write_access"
  695. , (collected_number) perf_events[EV_ID_L1D_WRITE_ACCESS].value
  696. );
  697. }
  698. if(likely(perf_events[EV_ID_L1D_WRITE_MISS].updated)) {
  699. printf(
  700. "SET %s = %lld\n"
  701. , "write_misses"
  702. , (collected_number) perf_events[EV_ID_L1D_WRITE_MISS].value
  703. );
  704. }
  705. printf("END\n");
  706. }
  707. // ------------------------------------------------------------------------
  708. if(likely(perf_events[EV_ID_L1D_PREFETCH_ACCESS].updated)) {
  709. if(unlikely(!L1D_prefetch_chart_generated)) {
  710. L1D_prefetch_chart_generated = 1;
  711. printf("CHART %s.%s '' 'L1D prefetch cache operations' 'prefetches/s' %s '' line %d %d '' %s\n"
  712. , RRD_TYPE_PERF
  713. , "l1d_cache_prefetch"
  714. , RRD_FAMILY_CACHE
  715. , NETDATA_CHART_PRIO_PERF_L1D_PREFETCH
  716. , update_every
  717. , PLUGIN_PERF_NAME
  718. );
  719. printf("DIMENSION %s '' absolute 1 1\n", "prefetches");
  720. }
  721. printf(
  722. "BEGIN %s.%s\n"
  723. , RRD_TYPE_PERF
  724. , "l1d_cache_prefetch"
  725. );
  726. printf(
  727. "SET %s = %lld\n"
  728. , "prefetches"
  729. , (collected_number) perf_events[EV_ID_L1D_PREFETCH_ACCESS].value
  730. );
  731. printf("END\n");
  732. }
  733. // ------------------------------------------------------------------------
  734. if(likely(perf_events[EV_ID_L1I_READ_ACCESS].updated || perf_events[EV_ID_L1I_READ_MISS].updated)) {
  735. if(unlikely(!L1I_chart_generated)) {
  736. L1I_chart_generated = 1;
  737. printf("CHART %s.%s '' 'L1I cache operations' 'events/s' %s '' line %d %d '' %s\n"
  738. , RRD_TYPE_PERF
  739. , "l1i_cache"
  740. , RRD_FAMILY_CACHE
  741. , NETDATA_CHART_PRIO_PERF_L1I
  742. , update_every
  743. , PLUGIN_PERF_NAME
  744. );
  745. printf("DIMENSION %s '' absolute 1 1\n", "read_access");
  746. printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
  747. }
  748. printf(
  749. "BEGIN %s.%s\n"
  750. , RRD_TYPE_PERF
  751. , "l1i_cache"
  752. );
  753. if(likely(perf_events[EV_ID_L1I_READ_ACCESS].updated)) {
  754. printf(
  755. "SET %s = %lld\n"
  756. , "read_access"
  757. , (collected_number) perf_events[EV_ID_L1I_READ_ACCESS].value
  758. );
  759. }
  760. if(likely(perf_events[EV_ID_L1I_READ_MISS].updated)) {
  761. printf(
  762. "SET %s = %lld\n"
  763. , "read_misses"
  764. , (collected_number) perf_events[EV_ID_L1I_READ_MISS].value
  765. );
  766. }
  767. printf("END\n");
  768. }
  769. // ------------------------------------------------------------------------
  770. if(likely(perf_events[EV_ID_LL_READ_ACCESS].updated || perf_events[EV_ID_LL_READ_MISS].updated
  771. || perf_events[EV_ID_LL_WRITE_ACCESS].updated || perf_events[EV_ID_LL_WRITE_MISS].updated)) {
  772. if(unlikely(!LL_chart_generated)) {
  773. LL_chart_generated = 1;
  774. printf("CHART %s.%s '' 'LL cache operations' 'events/s' %s '' line %d %d '' %s\n"
  775. , RRD_TYPE_PERF
  776. , "ll_cache"
  777. , RRD_FAMILY_CACHE
  778. , NETDATA_CHART_PRIO_PERF_LL
  779. , update_every
  780. , PLUGIN_PERF_NAME
  781. );
  782. printf("DIMENSION %s '' absolute 1 1\n", "read_access");
  783. printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
  784. printf("DIMENSION %s '' absolute -1 1\n", "write_access");
  785. printf("DIMENSION %s '' absolute -1 1\n", "write_misses");
  786. }
  787. printf(
  788. "BEGIN %s.%s\n"
  789. , RRD_TYPE_PERF
  790. , "ll_cache"
  791. );
  792. if(likely(perf_events[EV_ID_LL_READ_ACCESS].updated)) {
  793. printf(
  794. "SET %s = %lld\n"
  795. , "read_access"
  796. , (collected_number) perf_events[EV_ID_LL_READ_ACCESS].value
  797. );
  798. }
  799. if(likely(perf_events[EV_ID_LL_READ_MISS].updated)) {
  800. printf(
  801. "SET %s = %lld\n"
  802. , "read_misses"
  803. , (collected_number) perf_events[EV_ID_LL_READ_MISS].value
  804. );
  805. }
  806. if(likely(perf_events[EV_ID_LL_WRITE_ACCESS].updated)) {
  807. printf(
  808. "SET %s = %lld\n"
  809. , "write_access"
  810. , (collected_number) perf_events[EV_ID_LL_WRITE_ACCESS].value
  811. );
  812. }
  813. if(likely(perf_events[EV_ID_LL_WRITE_MISS].updated)) {
  814. printf(
  815. "SET %s = %lld\n"
  816. , "write_misses"
  817. , (collected_number) perf_events[EV_ID_LL_WRITE_MISS].value
  818. );
  819. }
  820. printf("END\n");
  821. }
  822. // ------------------------------------------------------------------------
  823. if(likely(perf_events[EV_ID_DTLB_READ_ACCESS].updated || perf_events[EV_ID_DTLB_READ_MISS].updated
  824. || perf_events[EV_ID_DTLB_WRITE_ACCESS].updated || perf_events[EV_ID_DTLB_WRITE_MISS].updated)) {
  825. if(unlikely(!DTLB_chart_generated)) {
  826. DTLB_chart_generated = 1;
  827. printf("CHART %s.%s '' 'DTLB cache operations' 'events/s' %s '' line %d %d '' %s\n"
  828. , RRD_TYPE_PERF
  829. , "dtlb_cache"
  830. , RRD_FAMILY_CACHE
  831. , NETDATA_CHART_PRIO_PERF_DTLB
  832. , update_every
  833. , PLUGIN_PERF_NAME
  834. );
  835. printf("DIMENSION %s '' absolute 1 1\n", "read_access");
  836. printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
  837. printf("DIMENSION %s '' absolute -1 1\n", "write_access");
  838. printf("DIMENSION %s '' absolute -1 1\n", "write_misses");
  839. }
  840. printf(
  841. "BEGIN %s.%s\n"
  842. , RRD_TYPE_PERF
  843. , "dtlb_cache"
  844. );
  845. if(likely(perf_events[EV_ID_DTLB_READ_ACCESS].updated)) {
  846. printf(
  847. "SET %s = %lld\n"
  848. , "read_access"
  849. , (collected_number) perf_events[EV_ID_DTLB_READ_ACCESS].value
  850. );
  851. }
  852. if(likely(perf_events[EV_ID_DTLB_READ_MISS].updated)) {
  853. printf(
  854. "SET %s = %lld\n"
  855. , "read_misses"
  856. , (collected_number) perf_events[EV_ID_DTLB_READ_MISS].value
  857. );
  858. }
  859. if(likely(perf_events[EV_ID_DTLB_WRITE_ACCESS].updated)) {
  860. printf(
  861. "SET %s = %lld\n"
  862. , "write_access"
  863. , (collected_number) perf_events[EV_ID_DTLB_WRITE_ACCESS].value
  864. );
  865. }
  866. if(likely(perf_events[EV_ID_DTLB_WRITE_MISS].updated)) {
  867. printf(
  868. "SET %s = %lld\n"
  869. , "write_misses"
  870. , (collected_number) perf_events[EV_ID_DTLB_WRITE_MISS].value
  871. );
  872. }
  873. printf("END\n");
  874. }
  875. // ------------------------------------------------------------------------
  876. if(likely(perf_events[EV_ID_ITLB_READ_ACCESS].updated || perf_events[EV_ID_ITLB_READ_MISS].updated)) {
  877. if(unlikely(!ITLB_chart_generated)) {
  878. ITLB_chart_generated = 1;
  879. printf("CHART %s.%s '' 'ITLB cache operations' 'events/s' %s '' line %d %d '' %s\n"
  880. , RRD_TYPE_PERF
  881. , "itlb_cache"
  882. , RRD_FAMILY_CACHE
  883. , NETDATA_CHART_PRIO_PERF_ITLB
  884. , update_every
  885. , PLUGIN_PERF_NAME
  886. );
  887. printf("DIMENSION %s '' absolute 1 1\n", "read_access");
  888. printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
  889. }
  890. printf(
  891. "BEGIN %s.%s\n"
  892. , RRD_TYPE_PERF
  893. , "itlb_cache"
  894. );
  895. if(likely(perf_events[EV_ID_ITLB_READ_ACCESS].updated)) {
  896. printf(
  897. "SET %s = %lld\n"
  898. , "read_access"
  899. , (collected_number) perf_events[EV_ID_ITLB_READ_ACCESS].value
  900. );
  901. }
  902. if(likely(perf_events[EV_ID_ITLB_READ_MISS].updated)) {
  903. printf(
  904. "SET %s = %lld\n"
  905. , "read_misses"
  906. , (collected_number) perf_events[EV_ID_ITLB_READ_MISS].value
  907. );
  908. }
  909. printf("END\n");
  910. }
  911. // ------------------------------------------------------------------------
  912. if(likely(perf_events[EV_ID_PBU_READ_ACCESS].updated)) {
  913. if(unlikely(!PBU_chart_generated)) {
  914. PBU_chart_generated = 1;
  915. printf("CHART %s.%s '' 'PBU cache operations' 'events/s' %s '' line %d %d '' %s\n"
  916. , RRD_TYPE_PERF
  917. , "pbu_cache"
  918. , RRD_FAMILY_CACHE
  919. , NETDATA_CHART_PRIO_PERF_PBU
  920. , update_every
  921. , PLUGIN_PERF_NAME
  922. );
  923. printf("DIMENSION %s '' absolute 1 1\n", "read_access");
  924. }
  925. printf(
  926. "BEGIN %s.%s\n"
  927. , RRD_TYPE_PERF
  928. , "pbu_cache"
  929. );
  930. printf(
  931. "SET %s = %lld\n"
  932. , "read_access"
  933. , (collected_number) perf_events[EV_ID_PBU_READ_ACCESS].value
  934. );
  935. printf("END\n");
  936. }
  937. }
  938. void parse_command_line(int argc, char **argv) {
  939. int i, plugin_enabled = 0;
  940. for(i = 1; i < argc ; i++) {
  941. if(isdigit(*argv[i]) && !freq) {
  942. int n = str2i(argv[i]);
  943. if(n > 0 && n < 86400) {
  944. freq = n;
  945. continue;
  946. }
  947. }
  948. else if(strcmp("version", argv[i]) == 0 || strcmp("-version", argv[i]) == 0 || strcmp("--version", argv[i]) == 0 || strcmp("-v", argv[i]) == 0 || strcmp("-V", argv[i]) == 0) {
  949. printf("perf.plugin %s\n", VERSION);
  950. exit(0);
  951. }
  952. else if(strcmp("all", argv[i]) == 0) {
  953. struct perf_event *current_event = NULL;
  954. for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++)
  955. current_event->disabled = 0;
  956. plugin_enabled = 1;
  957. continue;
  958. }
  959. else if(strcmp("cycles", argv[i]) == 0) {
  960. perf_events[EV_ID_CPU_CYCLES].disabled = 0;
  961. perf_events[EV_ID_REF_CPU_CYCLES].disabled = 0;
  962. plugin_enabled = 1;
  963. continue;
  964. }
  965. else if(strcmp("instructions", argv[i]) == 0) {
  966. perf_events[EV_ID_INSTRUCTIONS].disabled = 0;
  967. plugin_enabled = 1;
  968. continue;
  969. }
  970. else if(strcmp("branch", argv[i]) == 0) {
  971. perf_events[EV_ID_BRANCH_INSTRUCTIONS].disabled = 0;
  972. perf_events[EV_ID_BRANCH_MISSES].disabled = 0;
  973. plugin_enabled = 1;
  974. continue;
  975. }
  976. else if(strcmp("cache", argv[i]) == 0) {
  977. perf_events[EV_ID_CACHE_REFERENCES].disabled = 0;
  978. perf_events[EV_ID_CACHE_MISSES].disabled = 0;
  979. plugin_enabled = 1;
  980. continue;
  981. }
  982. else if(strcmp("bus", argv[i]) == 0) {
  983. perf_events[EV_ID_BUS_CYCLES].disabled = 0;
  984. plugin_enabled = 1;
  985. continue;
  986. }
  987. else if(strcmp("stalled", argv[i]) == 0) {
  988. perf_events[EV_ID_STALLED_CYCLES_FRONTEND].disabled = 0;
  989. perf_events[EV_ID_STALLED_CYCLES_BACKEND].disabled = 0;
  990. plugin_enabled = 1;
  991. continue;
  992. }
  993. else if(strcmp("migrations", argv[i]) == 0) {
  994. perf_events[EV_ID_CPU_MIGRATIONS].disabled = 0;
  995. plugin_enabled = 1;
  996. continue;
  997. }
  998. else if(strcmp("alignment", argv[i]) == 0) {
  999. perf_events[EV_ID_ALIGNMENT_FAULTS].disabled = 0;
  1000. plugin_enabled = 1;
  1001. continue;
  1002. }
  1003. else if(strcmp("emulation", argv[i]) == 0) {
  1004. perf_events[EV_ID_EMULATION_FAULTS].disabled = 0;
  1005. plugin_enabled = 1;
  1006. continue;
  1007. }
  1008. else if(strcmp("L1D", argv[i]) == 0) {
  1009. perf_events[EV_ID_L1D_READ_ACCESS].disabled = 0;
  1010. perf_events[EV_ID_L1D_READ_MISS].disabled = 0;
  1011. perf_events[EV_ID_L1D_WRITE_ACCESS].disabled = 0;
  1012. perf_events[EV_ID_L1D_WRITE_MISS].disabled = 0;
  1013. plugin_enabled = 1;
  1014. continue;
  1015. }
  1016. else if(strcmp("L1D-prefetch", argv[i]) == 0) {
  1017. perf_events[EV_ID_L1D_PREFETCH_ACCESS].disabled = 0;
  1018. plugin_enabled = 1;
  1019. continue;
  1020. }
  1021. else if(strcmp("L1I", argv[i]) == 0) {
  1022. perf_events[EV_ID_L1I_READ_ACCESS].disabled = 0;
  1023. perf_events[EV_ID_L1I_READ_MISS].disabled = 0;
  1024. plugin_enabled = 1;
  1025. continue;
  1026. }
  1027. else if(strcmp("LL", argv[i]) == 0) {
  1028. perf_events[EV_ID_LL_READ_ACCESS].disabled = 0;
  1029. perf_events[EV_ID_LL_READ_MISS].disabled = 0;
  1030. perf_events[EV_ID_LL_WRITE_ACCESS].disabled = 0;
  1031. perf_events[EV_ID_LL_WRITE_MISS].disabled = 0;
  1032. plugin_enabled = 1;
  1033. continue;
  1034. }
  1035. else if(strcmp("DTLB", argv[i]) == 0) {
  1036. perf_events[EV_ID_DTLB_READ_ACCESS].disabled = 0;
  1037. perf_events[EV_ID_DTLB_READ_MISS].disabled = 0;
  1038. perf_events[EV_ID_DTLB_WRITE_ACCESS].disabled = 0;
  1039. perf_events[EV_ID_DTLB_WRITE_MISS].disabled = 0;
  1040. plugin_enabled = 1;
  1041. continue;
  1042. }
  1043. else if(strcmp("ITLB", argv[i]) == 0) {
  1044. perf_events[EV_ID_ITLB_READ_ACCESS].disabled = 0;
  1045. perf_events[EV_ID_ITLB_READ_MISS].disabled = 0;
  1046. plugin_enabled = 1;
  1047. continue;
  1048. }
  1049. else if(strcmp("PBU", argv[i]) == 0) {
  1050. perf_events[EV_ID_PBU_READ_ACCESS].disabled = 0;
  1051. plugin_enabled = 1;
  1052. continue;
  1053. }
  1054. else if(strcmp("debug", argv[i]) == 0) {
  1055. debug = 1;
  1056. continue;
  1057. }
  1058. else if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
  1059. fprintf(stderr,
  1060. "\n"
  1061. " netdata perf.plugin %s\n"
  1062. " Copyright (C) 2019 Netdata Inc.\n"
  1063. " Released under GNU General Public License v3 or later.\n"
  1064. " All rights reserved.\n"
  1065. "\n"
  1066. " This program is a data collector plugin for netdata.\n"
  1067. "\n"
  1068. " Available command line options:\n"
  1069. "\n"
  1070. " COLLECTION_FREQUENCY data collection frequency in seconds\n"
  1071. " minimum: %d\n"
  1072. "\n"
  1073. " all enable all charts\n"
  1074. "\n"
  1075. " cycles enable CPU cycles chart\n"
  1076. "\n"
  1077. " instructions enable Instructions chart\n"
  1078. "\n"
  1079. " branch enable Branch instructions chart\n"
  1080. "\n"
  1081. " cache enable Cache operations chart\n"
  1082. "\n"
  1083. " bus enable Bus cycles chart\n"
  1084. "\n"
  1085. " stalled enable Stalled frontend and backend cycles chart\n"
  1086. "\n"
  1087. " migrations enable CPU migrations chart\n"
  1088. "\n"
  1089. " alignment enable Alignment faults chart\n"
  1090. "\n"
  1091. " emulation enable Emulation faults chart\n"
  1092. "\n"
  1093. " L1D enable L1D cache operations chart\n"
  1094. "\n"
  1095. " L1D-prefetch enable L1D prefetch cache operations chart\n"
  1096. "\n"
  1097. " L1I enable L1I cache operations chart\n"
  1098. "\n"
  1099. " LL enable LL cache operations chart\n"
  1100. "\n"
  1101. " DTLB enable DTLB cache operations chart\n"
  1102. "\n"
  1103. " ITLB enable ITLB cache operations chart\n"
  1104. "\n"
  1105. " PBU enable PBU cache operations chart\n"
  1106. "\n"
  1107. " debug enable verbose output\n"
  1108. " default: disabled\n"
  1109. "\n"
  1110. " -v\n"
  1111. " -V\n"
  1112. " --version print version and exit\n"
  1113. "\n"
  1114. " -h\n"
  1115. " --help print this message and exit\n"
  1116. "\n"
  1117. " For more information:\n"
  1118. " https://github.com/netdata/netdata/tree/master/collectors/perf.plugin\n"
  1119. "\n"
  1120. , VERSION
  1121. , update_every
  1122. );
  1123. exit(1);
  1124. }
  1125. collector_error("ignoring parameter '%s'", argv[i]);
  1126. }
  1127. if(!plugin_enabled){
  1128. collector_info("no charts enabled - nothing to do.");
  1129. printf("DISABLE\n");
  1130. exit(1);
  1131. }
  1132. }
  1133. int main(int argc, char **argv) {
  1134. clocks_init();
  1135. nd_log_initialize_for_external_plugins("perf.plugin");
  1136. parse_command_line(argc, argv);
  1137. errno = 0;
  1138. if(freq >= update_every)
  1139. update_every = freq;
  1140. else if(freq)
  1141. collector_error("update frequency %d seconds is too small for PERF. Using %d.", freq, update_every);
  1142. if(unlikely(debug)) fprintf(stderr, "perf.plugin: calling perf_init()\n");
  1143. int perf = !perf_init();
  1144. // ------------------------------------------------------------------------
  1145. // the main loop
  1146. if(unlikely(debug)) fprintf(stderr, "perf.plugin: starting data collection\n");
  1147. time_t started_t = now_monotonic_sec();
  1148. size_t iteration;
  1149. usec_t step = update_every * USEC_PER_SEC;
  1150. heartbeat_t hb;
  1151. heartbeat_init(&hb);
  1152. for(iteration = 0; 1; iteration++) {
  1153. usec_t dt = heartbeat_next(&hb, step);
  1154. if(unlikely(netdata_exit)) break;
  1155. if(unlikely(debug && iteration))
  1156. fprintf(stderr, "perf.plugin: iteration %zu, dt %"PRIu64" usec\n"
  1157. , iteration
  1158. , dt
  1159. );
  1160. if(likely(perf)) {
  1161. if(unlikely(debug)) fprintf(stderr, "perf.plugin: calling perf_collect()\n");
  1162. perf = !perf_collect();
  1163. if(likely(perf)) {
  1164. if(unlikely(debug)) fprintf(stderr, "perf.plugin: calling perf_send_metrics()\n");
  1165. perf_send_metrics();
  1166. }
  1167. }
  1168. fflush(stdout);
  1169. // restart check (14400 seconds)
  1170. if(now_monotonic_sec() - started_t > 14400) break;
  1171. }
  1172. collector_info("process exiting");
  1173. perf_free();
  1174. }