perf_plugin.c 50 KB

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