@cryptotaxi247 / netdata-1 / commits / 21cd00c84

Perf plugin (#6225)

* Add perf plugin skeleton * Initialize events * Collect data * Configure default counters * Add charts for hardware and software counters * Add charts for cache counters * Don't show zeroes for non-existent metrics * Reinit events when stalled * Do not reinit disabled events * Update the documentation * Scale values when multiplexing is happening

Vladimir Kobal committed Jun 20, 2019 at 15:23 UTC 21cd00c84a468d12d55d60f4fff91aac3bce847e
15 files changed +1515 -15
.gitignore
+3
@@ -56,6 +56,9 @@ nfacct.plugin
56 xenstat.plugin
57 !xenstat.plugin/
58
59 +perf.plugin
60 +!perf.plugin/
61 +
62 cgroup-network
63 !cgroup-network/
64
CMakeLists.txt
+21
@@ -370,6 +370,10 @@ set(XENSTAT_PLUGIN_FILES
370 collectors/xenstat.plugin/xenstat_plugin.c
371 )
372
373 +set(PERF_PLUGIN_FILES
374 + collectors/perf.plugin/perf_plugin.c
375 + )
376 +
377 set(PROC_PLUGIN_FILES
378 collectors/proc.plugin/ipc.c
379 collectors/proc.plugin/plugin_proc.c
@@ -678,6 +682,7 @@ IF(LINUX)
682
683 SET(ENABLE_PLUGIN_CGROUP_NETWORK True)
684 SET(ENABLE_PLUGIN_APPS True)
685 + SET(ENABLE_PLUGIN_PERF True)
686
687 ELSEIF(FREEBSD)
688 add_executable(netdata config.h ${NETDATA_FILES} ${FREEBSD_PLUGIN_FILES})
@@ -686,6 +691,7 @@ ELSEIF(FREEBSD)
691 target_compile_options(netdata PUBLIC ${NETDATA_COMMON_CFLAGS})
692 SET(ENABLE_PLUGIN_CGROUP_NETWORK False)
693 SET(ENABLE_PLUGIN_APPS True)
694 + SET(ENABLE_PLUGIN_PERF False)
695
696 ELSEIF(MACOS)
697 add_executable(netdata config.h ${NETDATA_FILES} ${MACOS_PLUGIN_FILES})
@@ -694,6 +700,7 @@ ELSEIF(MACOS)
700 target_compile_options(netdata PUBLIC ${NETDATA_COMMON_CFLAGS})
701 SET(ENABLE_PLUGIN_CGROUP_NETWORK False)
702 SET(ENABLE_PLUGIN_APPS False)
703 + SET(ENABLE_PLUGIN_PERF False)
704
705 ENDIF()
706
@@ -777,6 +784,20 @@ ELSE()
784 ENDIF()
785
786
787 +# -----------------------------------------------------------------------------
788 +# perf.plugin
789 +
790 +IF(ENABLE_PLUGIN_PERF)
791 + message(STATUS "perf.plugin: enabled")
792 + add_executable(perf.plugin config.h ${PERF_PLUGIN_FILES})
793 + target_link_libraries (perf.plugin libnetdata ${NETDATA_COMMON_LIBRARIES})
794 + target_include_directories(perf.plugin PUBLIC ${NETDATA_COMMON_INCLUDE_DIRS})
795 + target_compile_options(perf.plugin PUBLIC ${NETDATA_COMMON_CFLAGS})
796 +ELSE()
797 + message(STATUS "perf.plugin: disabled")
798 +ENDIF()
799 +
800 +
801 # -----------------------------------------------------------------------------
802 # cgroup-network
803
Makefile.am
+13
@@ -234,6 +234,11 @@ XENSTAT_PLUGIN_FILES = \
234 $(LIBNETDATA_FILES) \
235 $(NULL)
236
237 +PERF_PLUGIN_FILES = \
238 + collectors/perf.plugin/perf_plugin.c \
239 + $(LIBNETDATA_FILES) \
240 + $(NULL)
241 +
242 PROC_PLUGIN_FILES = \
243 collectors/proc.plugin/ipc.c \
244 collectors/proc.plugin/plugin_proc.c \
@@ -573,6 +578,14 @@ if ENABLE_PLUGIN_XENSTAT
578 $(NULL)
579 endif
580
581 +if ENABLE_PLUGIN_PERF
582 + plugins_PROGRAMS += perf.plugin
583 + perf_plugin_SOURCES = $(PERF_PLUGIN_FILES)
584 + perf_plugin_LDADD = \
585 + $(NETDATA_COMMON_LIBS) \
586 + $(NULL)
587 +endif
588 +
589 if ENABLE_BACKEND_KINESIS
590 netdata_SOURCES += $(KINESIS_BACKEND_FILES)
591 netdata_LDADD += $(OPTIONAL_KINESIS_LIBS)
collectors/Makefile.am
+1
@@ -18,6 +18,7 @@ SUBDIRS = \
18 macos.plugin \
19 nfacct.plugin \
20 xenstat.plugin \
21 + perf.plugin \
22 node.d.plugin \
23 proc.plugin \
24 python.d.plugin \
collectors/README.md
+1
@@ -37,6 +37,7 @@ plugin|lang|O/S|runs as|modular|description
37 [macos.plugin](macos.plugin/)|`C`|macos|internal|yes|collects resource usage and performance data on MacOS systems
38 [nfacct.plugin](nfacct.plugin/)|`C`|linux|external|-|collects netfilter firewall, connection tracker and accounting metrics using `libmnl` and `libnetfilter_acct`
39 [xenstat.plugin](xenstat.plugin/)|`C`|linux|external|-|collects XenServer and XCP-ng metrics using `libxenstat`
40 +[perf.plugin](perf.plugin/)|`C`|linux|external|-|collects CPU performance metrics using performance monitoring units (PMU).
41 [node.d.plugin](node.d.plugin/)|`node.js`|any|external|yes|a **plugin orchestrator** for data collection modules written in `node.js`.
42 [plugins.d](plugins.d/)|`C`|any|internal|-|implements the **external plugins** API and serves external plugins
43 [proc.plugin](proc.plugin/)|`C`|linux|internal|yes|collects resource usage and performance data on Linux systems
collectors/apps.plugin/apps_groups.conf
+1
@@ -77,6 +77,7 @@ freeipmi.plugin: freeipmi.plugin
77 nfacct.plugin: nfacct.plugin
78 cups.plugin: cups.plugin
79 xenstat.plugin: xenstat.plugin
80 +perf.plugin: perf.plugin
81 charts.d.plugin: *charts.d.plugin*
82 node.d.plugin: *node.d.plugin*
83 python.d.plugin: *python.d.plugin*
collectors/perf.plugin/Makefile.am new
+8
@@ -0,0 +1,8 @@
1 +# SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +AUTOMAKE_OPTIONS = subdir-objects
4 +MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5 +
6 +dist_noinst_DATA = \
7 + README.md \
8 + $(NULL)
collectors/perf.plugin/README.md new
+72
@@ -0,0 +1,72 @@
1 +# perf.plugin
2 +
3 +`perf.plugin` collects system-wide CPU performance statistics from Performance Monitoring Units (PMU) using
4 +the `perf_event_open()` system call.
5 +
6 +## Important Notes
7 +
8 +Accessing hardware PMUs requires root permissions, so the plugin is setuid to root.
9 +
10 +Keep in mind that the number of PMUs in a system is usually quite limited and every hardware monitoring
11 +event for every CPU core needs a separate file descriptor to be opened.
12 +
13 +## Charts
14 +
15 +The plugin provides statistics for general hardware and software performance monitoring events:
16 +
17 +Hardware events:
18 +1. CPU cycles
19 +2. Instructions
20 +3. Branch instructions
21 +4. Cache operations
22 +5. BUS cycles
23 +6. Stalled frontend and backend cycles
24 +
25 +Software events:
26 +1. CPU migrations
27 +2. Alignment faults
28 +3. Emulation faults
29 +
30 +Hardware cache events:
31 +1. L1D cache operations
32 +2. L1D prefetch cache operations
33 +3. L1I cache operations
34 +4. LL cache operations
35 +5. DTLB cache operations
36 +6. ITLB cache operations
37 +7. PBU cache operations
38 +
39 +## Configuration
40 +
41 +The plugin is disabled by default because the number of PMUs is usually quite limited and it is not desired to
42 +allow Netdata to struggle silently for PMUs, interfering with other performance monitoring software. If you need to
43 +enable the perf plugin, edit /etc/netdata/netdata.conf and set:
44 +
45 +```raw
46 +[plugins]
47 + perf = yes
48 +```
49 +
50 +```raw
51 +[plugin:perf]
52 + update every = 1
53 + command options = all
54 +```
55 +
56 +You can use the `command options` parameter to pick what data should be collected and which charts should be
57 +displayed. If `all` is used, all general performance monitoring counters are probed and corresponding charts
58 +are enabled for the available counters. You can also define a particular set of enabled charts using the
59 +following keywords: `cycles`, `instructions`, `branch`, `cache`, `bus`, `stalled`, `migrations`, `alighnment`,
60 +`emulation`, `L1D`, `L1D-prefetch`, `L1I`, `LL`, `DTLB`, `ITLB`, `PBU`.
61 +
62 +## Debugging
63 +
64 +You can run the plugin by hand:
65 +
66 +```raw
67 +sudo /usr/libexec/netdata/plugins.d/perf.plugin 1 all debug
68 +```
69 +
70 +You will get verbose output on what the plugin does.
71 +
72 +[![analytics](https://www.google-analytics.com/collect?v=1&aip=1&t=pageview&_s=1&ds=github&dr=https%3A%2F%2Fgithub.com%2Fnetdata%2Fnetdata&dl=https%3A%2F%2Fmy-netdata.io%2Fgithub%2Fcollectors%2Fperf.plugin%2FREADME&_u=MAC~&cid=5792dfd7-8dc4-476b-af31-da2fdb9f93d2&tid=UA-64295674-3)]()
collectors/perf.plugin/perf_plugin.c new
+1348
@@ -0,0 +1,1348 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "../../libnetdata/libnetdata.h"
4 +
5 +#include <linux/perf_event.h>
6 +
7 +#define PLUGIN_PERF_NAME "perf.plugin"
8 +
9 +// Hardware counters
10 +#define NETDATA_CHART_PRIO_PERF_CPU_CYCLES 8800
11 +#define NETDATA_CHART_PRIO_PERF_INSTRUCTIONS 8801
12 +#define NETDATA_CHART_PRIO_PERF_BRANCH_INSTRUSTIONS 8802
13 +#define NETDATA_CHART_PRIO_PERF_CACHE 8803
14 +#define NETDATA_CHART_PRIO_PERF_BUS_CYCLES 8804
15 +#define NETDATA_CHART_PRIO_PERF_FRONT_BACK_CYCLES 8805
16 +
17 +// Software counters
18 +#define NETDATA_CHART_PRIO_PERF_MIGRATIONS 8810
19 +#define NETDATA_CHART_PRIO_PERF_ALIGNMENT 8811
20 +#define NETDATA_CHART_PRIO_PERF_EMULATION 8812
21 +
22 +// Hardware cache counters
23 +#define NETDATA_CHART_PRIO_PERF_L1D 8820
24 +#define NETDATA_CHART_PRIO_PERF_L1D_PREFETCH 8821
25 +#define NETDATA_CHART_PRIO_PERF_L1I 8822
26 +#define NETDATA_CHART_PRIO_PERF_LL 8823
27 +#define NETDATA_CHART_PRIO_PERF_DTLB 8824
28 +#define NETDATA_CHART_PRIO_PERF_ITLB 8825
29 +#define NETDATA_CHART_PRIO_PERF_PBU 8826
30 +
31 +// callback required by fatal()
32 +void netdata_cleanup_and_exit(int ret) {
33 + exit(ret);
34 +}
35 +
36 +void send_statistics( const char *action, const char *action_result, const char *action_data) {
37 + (void) action;
38 + (void) action_result;
39 + (void) action_data;
40 + return;
41 +}
42 +
43 +// callbacks required by popen()
44 +void signals_block(void) {};
45 +void signals_unblock(void) {};
46 +void signals_reset(void) {};
47 +
48 +// callback required by eval()
49 +int health_variable_lookup(const char *variable, uint32_t hash, struct rrdcalc *rc, calculated_number *result) {
50 + (void)variable;
51 + (void)hash;
52 + (void)rc;
53 + (void)result;
54 + return 0;
55 +};
56 +
57 +// required by get_system_cpus()
58 +char *netdata_configured_host_prefix = "";
59 +
60 +// Variables
61 +
62 +#define RRD_TYPE_PERF "perf"
63 +#define RRD_FAMILY_HW "hardware"
64 +#define RRD_FAMILY_SW "software"
65 +#define RRD_FAMILY_CACHE "cache"
66 +
67 +#define NO_FD -1
68 +#define ALL_PIDS -1
69 +#define RUNNING_THRESHOLD 100
70 +
71 +static int debug = 0;
72 +
73 +static int update_every = 1;
74 +static int freq = 0;
75 +
76 +typedef enum perf_event_id {
77 + // Hardware counters
78 + EV_ID_CPU_CYCLES,
79 + EV_ID_INSTRUCTIONS,
80 + EV_ID_CACHE_REFERENCES,
81 + EV_ID_CACHE_MISSES,
82 + EV_ID_BRANCH_INSTRUCTIONS,
83 + EV_ID_BRANCH_MISSES,
84 + EV_ID_BUS_CYCLES,
85 + EV_ID_STALLED_CYCLES_FRONTEND,
86 + EV_ID_STALLED_CYCLES_BACKEND,
87 + EV_ID_REF_CPU_CYCLES,
88 +
89 + // Software counters
90 + // EV_ID_CPU_CLOCK,
91 + // EV_ID_TASK_CLOCK,
92 + // EV_ID_PAGE_FAULTS,
93 + // EV_ID_CONTEXT_SWITCHES,
94 + EV_ID_CPU_MIGRATIONS,
95 + // EV_ID_PAGE_FAULTS_MIN,
96 + // EV_ID_PAGE_FAULTS_MAJ,
97 + EV_ID_ALIGNMENT_FAULTS,
98 + EV_ID_EMULATION_FAULTS,
99 +
100 + // Hardware cache counters
101 + EV_ID_L1D_READ_ACCESS,
102 + EV_ID_L1D_READ_MISS,
103 + EV_ID_L1D_WRITE_ACCESS,
104 + EV_ID_L1D_WRITE_MISS,
105 + EV_ID_L1D_PREFETCH_ACCESS,
106 +
107 + EV_ID_L1I_READ_ACCESS,
108 + EV_ID_L1I_READ_MISS,
109 +
110 + EV_ID_LL_READ_ACCESS,
111 + EV_ID_LL_READ_MISS,
112 + EV_ID_LL_WRITE_ACCESS,
113 + EV_ID_LL_WRITE_MISS,
114 +
115 + EV_ID_DTLB_READ_ACCESS,
116 + EV_ID_DTLB_READ_MISS,
117 + EV_ID_DTLB_WRITE_ACCESS,
118 + EV_ID_DTLB_WRITE_MISS,
119 +
120 + EV_ID_ITLB_READ_ACCESS,
121 + EV_ID_ITLB_READ_MISS,
122 +
123 + EV_ID_PBU_READ_ACCESS,
124 +
125 + EV_ID_END
126 +} perf_event_id_t;
127 +
128 +enum perf_event_group {
129 + EV_GROUP_CYCLES,
130 + EV_GROUP_INSTRUCTIONS_AND_CACHE,
131 + EV_GROUP_SOFTWARE,
132 + EV_GROUP_CACHE_L1D,
133 + EV_GROUP_CACHE_L1I_LL_DTLB,
134 + EV_GROUP_CACHE_ITLB_BPU,
135 +
136 + EV_GROUP_NUM
137 +};
138 +
139 +static int number_of_cpus;
140 +
141 +static int *group_leader_fds[EV_GROUP_NUM];
142 +
143 +static struct perf_event {
144 + perf_event_id_t id;
145 +
146 + int type;
147 + int config;
148 +
149 + int **group_leader_fd;
150 + int *fd;
151 +
152 + int disabled;
153 + int updated;
154 +
155 + uint64_t value;
156 +
157 + uint64_t *prev_value;
158 + uint64_t *prev_time_enabled;
159 + uint64_t *prev_time_running;
160 +} perf_events[] = {
161 + // Hardware counters
162 + {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},
163 + {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},
164 + {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},
165 + {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},
166 + {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},
167 + {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},
168 + {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},
169 + {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},
170 + {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},
171 + {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},
172 +
173 + // Software counters
174 + // {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},
175 + // {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},
176 + // {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},
177 + // {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},
178 + {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},
179 + // {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},
180 + // {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},
181 + {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},
182 + {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},
183 +
184 + // Hardware cache counters
185 + {
186 + EV_ID_L1D_READ_ACCESS, PERF_TYPE_HW_CACHE,
187 + (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
188 + &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
189 + }, {
190 + EV_ID_L1D_READ_MISS, PERF_TYPE_HW_CACHE,
191 + (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
192 + &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
193 + }, {
194 + EV_ID_L1D_WRITE_ACCESS, PERF_TYPE_HW_CACHE,
195 + (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
196 + &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
197 + }, {
198 + EV_ID_L1D_WRITE_MISS, PERF_TYPE_HW_CACHE,
199 + (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
200 + &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
201 + }, {
202 + EV_ID_L1D_PREFETCH_ACCESS, PERF_TYPE_HW_CACHE,
203 + (PERF_COUNT_HW_CACHE_L1D) | (PERF_COUNT_HW_CACHE_OP_PREFETCH << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
204 + &group_leader_fds[EV_GROUP_CACHE_L1D], NULL, 1, 0, 0, NULL, NULL, NULL
205 + },
206 +
207 + {
208 + EV_ID_L1I_READ_ACCESS, PERF_TYPE_HW_CACHE,
209 + (PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
210 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
211 + }, {
212 + EV_ID_L1I_READ_MISS, PERF_TYPE_HW_CACHE,
213 + (PERF_COUNT_HW_CACHE_L1I) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
214 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
215 + },
216 +
217 + {
218 + EV_ID_LL_READ_ACCESS, PERF_TYPE_HW_CACHE,
219 + (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
220 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
221 + }, {
222 + EV_ID_LL_READ_MISS, PERF_TYPE_HW_CACHE,
223 + (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
224 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
225 + }, {
226 + EV_ID_LL_WRITE_ACCESS, PERF_TYPE_HW_CACHE,
227 + (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
228 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
229 + }, {
230 + EV_ID_LL_WRITE_MISS, PERF_TYPE_HW_CACHE,
231 + (PERF_COUNT_HW_CACHE_LL) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
232 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
233 + },
234 +
235 + {
236 + EV_ID_DTLB_READ_ACCESS, PERF_TYPE_HW_CACHE,
237 + (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
238 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
239 + }, {
240 + EV_ID_DTLB_READ_MISS, PERF_TYPE_HW_CACHE,
241 + (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
242 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
243 + }, {
244 + EV_ID_DTLB_WRITE_ACCESS, PERF_TYPE_HW_CACHE,
245 + (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
246 + &group_leader_fds[EV_GROUP_CACHE_L1I_LL_DTLB], NULL, 1, 0, 0, NULL, NULL, NULL
247 + }, {
248 + EV_ID_DTLB_WRITE_MISS, PERF_TYPE_HW_CACHE,
249 + (PERF_COUNT_HW_CACHE_DTLB) | (PERF_COUNT_HW_CACHE_OP_WRITE << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
250 + &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
251 + },
252 +
253 + {
254 + EV_ID_ITLB_READ_ACCESS, PERF_TYPE_HW_CACHE,
255 + (PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
256 + &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
257 + }, {
258 + EV_ID_ITLB_READ_MISS, PERF_TYPE_HW_CACHE,
259 + (PERF_COUNT_HW_CACHE_ITLB) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_MISS << 16),
260 + &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
261 + },
262 +
263 + {
264 + EV_ID_PBU_READ_ACCESS, PERF_TYPE_HW_CACHE,
265 + (PERF_COUNT_HW_CACHE_BPU) | (PERF_COUNT_HW_CACHE_OP_READ << 8) | (PERF_COUNT_HW_CACHE_RESULT_ACCESS << 16),
266 + &group_leader_fds[EV_GROUP_CACHE_ITLB_BPU], NULL, 1, 0, 0, NULL, NULL, NULL
267 + },
268 +
269 + {EV_ID_END, 0, 0, NULL, NULL, 0, 0, 0, NULL, NULL, NULL}
270 +};
271 +
272 +static int perf_init() {
273 + int cpu, group;
274 + struct perf_event_attr perf_event_attr;
275 + struct perf_event *current_event = NULL;
276 + unsigned long flags = 0;
277 +
278 + number_of_cpus = (int)get_system_cpus();
279 +
280 + // initialize all perf event file descriptors
281 + for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
282 + current_event->fd = mallocz(number_of_cpus * sizeof(int));
283 + memset(current_event->fd, NO_FD, number_of_cpus * sizeof(int));
284 +
285 + current_event->prev_value = mallocz(number_of_cpus * sizeof(uint64_t));
286 + memset(current_event->prev_value, 0, number_of_cpus * sizeof(uint64_t));
287 +
288 + current_event->prev_time_enabled = mallocz(number_of_cpus * sizeof(uint64_t));
289 + memset(current_event->prev_time_enabled, 0, number_of_cpus * sizeof(uint64_t));
290 +
291 + current_event->prev_time_running = mallocz(number_of_cpus * sizeof(uint64_t));
292 + memset(current_event->prev_time_running, 0, number_of_cpus * sizeof(uint64_t));
293 + }
294 +
295 + for(group = 0; group < EV_GROUP_NUM; group++) {
296 + group_leader_fds[group] = mallocz(number_of_cpus * sizeof(int));
297 + memset(group_leader_fds[group], NO_FD, number_of_cpus * sizeof(int));
298 + }
299 +
300 + memset(&perf_event_attr, 0, sizeof(perf_event_attr));
301 +
302 + for(cpu = 0; cpu < number_of_cpus; cpu++) {
303 + for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
304 + if(unlikely(current_event->disabled)) continue;
305 +
306 + perf_event_attr.type = current_event->type;
307 + perf_event_attr.config = current_event->config;
308 + perf_event_attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_TOTAL_TIME_RUNNING;
309 +
310 + int fd, group_leader_fd = *(*current_event->group_leader_fd + cpu);
311 +
312 + fd = syscall(
313 + __NR_perf_event_open,
314 + &perf_event_attr,
315 + ALL_PIDS,
316 + cpu,
317 + group_leader_fd,
318 + flags
319 + );
320 +
321 + if(unlikely(group_leader_fd == NO_FD)) group_leader_fd = fd;
322 +
323 + if(unlikely(fd < 0)) {
324 + switch errno {
325 + case EACCES:
326 + error("Cannot access to the PMU: Permission denied");
327 + break;
328 + case EBUSY:
329 + error("Another event already has exclusive access to the PMU");
330 + break;
331 + default:
332 + error("Cannot open perf event");
333 + }
334 + error("Disabling event %u", current_event->id);
335 + current_event->disabled = 1;
336 + }
337 +
338 + *(current_event->fd + cpu) = fd;
339 + *(*current_event->group_leader_fd + cpu) = group_leader_fd;
340 +
341 + 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);
342 + }
343 + }
344 +
345 + return 0;
346 +}
347 +
348 +static void perf_free(void) {
349 + int cpu, group;
350 + struct perf_event *current_event = NULL;
351 +
352 + for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
353 + for(cpu = 0; cpu < number_of_cpus; cpu++)
354 + if(*(current_event->fd + cpu) != NO_FD) close(*(current_event->fd + cpu));
355 +
356 + free(current_event->fd);
357 + free(current_event->prev_value);
358 + free(current_event->prev_time_enabled);
359 + free(current_event->prev_time_running);
360 + }
361 +
362 + for(group = 0; group < EV_GROUP_NUM; group++)
363 + free(group_leader_fds[group]);
364 +}
365 +
366 +static void reenable_events() {
367 + int group, cpu;
368 +
369 + for(group = 0; group < EV_GROUP_NUM; group++) {
370 + for(cpu = 0; cpu < number_of_cpus; cpu++) {
371 + int current_fd = *(group_leader_fds[group] + cpu);
372 +
373 + if(unlikely(current_fd == NO_FD)) continue;
374 +
375 + if(ioctl(current_fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP) == -1
376 + || ioctl(current_fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP) == -1)
377 + {
378 + error("Cannot reenable event group");
379 + }
380 + }
381 + }
382 +}
383 +
384 +static int perf_collect() {
385 + int cpu;
386 + struct perf_event *current_event = NULL;
387 + static uint64_t prev_cpu_cycles_value = 0;
388 + struct {
389 + uint64_t value;
390 + uint64_t time_enabled;
391 + uint64_t time_running;
392 + } read_result;
393 +
394 + for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++) {
395 + current_event->updated = 0;
396 + current_event->value = 0;
397 +
398 + if(unlikely(current_event->disabled)) continue;
399 +
400 + for(cpu = 0; cpu < number_of_cpus; cpu++) {
401 +
402 + ssize_t read_size = read(current_event->fd[cpu], &read_result, sizeof(read_result));
403 +
404 + if(likely(read_size == sizeof(read_result))) {
405 + if (likely(read_result.time_running
406 + && read_result.time_running != *(current_event->prev_time_running + cpu)
407 + && (read_result.time_enabled / read_result.time_running < RUNNING_THRESHOLD))) {
408 + current_event->value += (read_result.value - *(current_event->prev_value + cpu)) \
409 + * (read_result.time_enabled - *(current_event->prev_time_enabled + cpu)) \
410 + / (read_result.time_running - *(current_event->prev_time_running + cpu));
411 + }
412 +
413 + *(current_event->prev_value + cpu) = read_result.value;
414 + *(current_event->prev_time_enabled + cpu) = read_result.time_enabled;
415 + *(current_event->prev_time_running + cpu) = read_result.time_running;
416 +
417 + current_event->updated = 1;
418 + }
419 + else {
420 + error("Cannot update value for event %u", current_event->id);
421 + return 1;
422 + }
423 + }
424 +
425 + if(unlikely(debug)) fprintf(stderr, "perf.plugin: successfully read event id = %u, value = %lu\n", current_event->id, current_event->value);
426 + }
427 +
428 + if(unlikely(perf_events[EV_ID_CPU_CYCLES].value == prev_cpu_cycles_value))
429 + reenable_events();
430 + prev_cpu_cycles_value = perf_events[EV_ID_CPU_CYCLES].value;
431 +
432 + return 0;
433 +}
434 +
435 +static void perf_send_metrics() {
436 + static int // Hardware counters
437 + cpu_cycles_chart_generated = 0,
438 + instructions_chart_generated = 0,
439 + branch_chart_generated = 0,
440 + cache_chart_generated = 0,
441 + bus_cycles_chart_generated = 0,
442 + stalled_cycles_chart_generated = 0,
443 +
444 + // Software counters
445 + migrations_chart_generated = 0,
446 + alighnment_chart_generated = 0,
447 + emulation_chart_generated = 0,
448 +
449 + // Hardware cache counters
450 + L1D_chart_generated = 0,
451 + L1D_prefetch_chart_generated = 0,
452 + L1I_chart_generated = 0,
453 + LL_chart_generated = 0,
454 + DTLB_chart_generated = 0,
455 + ITLB_chart_generated = 0,
456 + PBU_chart_generated = 0;
457 +
458 + // ------------------------------------------------------------------------
459 +
460 + if(likely(perf_events[EV_ID_CPU_CYCLES].updated || perf_events[EV_ID_REF_CPU_CYCLES].updated)) {
461 + if(unlikely(!cpu_cycles_chart_generated)) {
462 + cpu_cycles_chart_generated = 1;
463 +
464 + printf("CHART %s.%s '' 'CPU cycles' 'cycles/s' %s '' line %d %d %s\n"
465 + , RRD_TYPE_PERF
466 + , "cpu_cycles"
467 + , RRD_FAMILY_HW
468 + , NETDATA_CHART_PRIO_PERF_CPU_CYCLES
469 + , update_every
470 + , PLUGIN_PERF_NAME
471 + );
472 + printf("DIMENSION %s '' absolute 1 1\n", "cpu");
473 + printf("DIMENSION %s '' absolute 1 1\n", "ref_cpu");
474 + }
475 +
476 + printf(
477 + "BEGIN %s.%s\n"
478 + , RRD_TYPE_PERF
479 + , "cpu_cycles"
480 + );
481 + if(likely(perf_events[EV_ID_CPU_CYCLES].updated)) {
482 + printf(
483 + "SET %s = %lld\n"
484 + , "cpu"
485 + , (collected_number) perf_events[EV_ID_CPU_CYCLES].value
486 + );
487 + }
488 + if(likely(perf_events[EV_ID_REF_CPU_CYCLES].updated)) {
489 + printf(
490 + "SET %s = %lld\n"
491 + , "ref_cpu"
492 + , (collected_number) perf_events[EV_ID_REF_CPU_CYCLES].value
493 + );
494 + }
495 + printf("END\n");
496 + }
497 +
498 + // ------------------------------------------------------------------------
499 +
500 + if(likely(perf_events[EV_ID_INSTRUCTIONS].updated)) {
501 + if(unlikely(!instructions_chart_generated)) {
502 + instructions_chart_generated = 1;
503 +
504 + printf("CHART %s.%s '' 'Instructions' 'instructions/s' %s '' line %d %d %s\n"
505 + , RRD_TYPE_PERF
506 + , "instructions"
507 + , RRD_FAMILY_HW
508 + , NETDATA_CHART_PRIO_PERF_INSTRUCTIONS
509 + , update_every
510 + , PLUGIN_PERF_NAME
511 + );
512 + printf("DIMENSION %s '' absolute 1 1\n", "instructions");
513 + }
514 +
515 + printf(
516 + "BEGIN %s.%s\n"
517 + , RRD_TYPE_PERF
518 + , "instructions"
519 + );
520 + printf(
521 + "SET %s = %lld\n"
522 + , "instructions"
523 + , (collected_number) perf_events[EV_ID_INSTRUCTIONS].value
524 + );
525 + printf("END\n");
526 + }
527 +
528 + // ------------------------------------------------------------------------
529 +
530 + if(likely(perf_events[EV_ID_BRANCH_INSTRUCTIONS].updated || perf_events[EV_ID_BRANCH_MISSES].updated)) {
531 + if(unlikely(!branch_chart_generated)) {
532 + branch_chart_generated = 1;
533 +
534 + printf("CHART %s.%s '' 'Branch instructions' 'instructions/s' %s '' line %d %d %s\n"
535 + , RRD_TYPE_PERF
536 + , "branch_instructions"
537 + , RRD_FAMILY_HW
538 + , NETDATA_CHART_PRIO_PERF_BRANCH_INSTRUSTIONS
539 + , update_every
540 + , PLUGIN_PERF_NAME
541 + );
542 + printf("DIMENSION %s '' absolute 1 1\n", "instructions");
543 + printf("DIMENSION %s '' absolute 1 1\n", "misses");
544 + }
545 +
546 + printf(
547 + "BEGIN %s.%s\n"
548 + , RRD_TYPE_PERF
549 + , "branch_instructions"
550 + );
551 + if(likely(perf_events[EV_ID_BRANCH_INSTRUCTIONS].updated)) {
552 + printf(
553 + "SET %s = %lld\n"
554 + , "instructions"
555 + , (collected_number) perf_events[EV_ID_BRANCH_INSTRUCTIONS].value
556 + );
557 + }
558 + if(likely(perf_events[EV_ID_BRANCH_MISSES].updated)) {
559 + printf(
560 + "SET %s = %lld\n"
561 + , "misses"
562 + , (collected_number) perf_events[EV_ID_BRANCH_MISSES].value
563 + );
564 + }
565 + printf("END\n");
566 + }
567 +
568 + // ------------------------------------------------------------------------
569 +
570 + if(likely(perf_events[EV_ID_CACHE_REFERENCES].updated || perf_events[EV_ID_CACHE_MISSES].updated)) {
571 + if(unlikely(!cache_chart_generated)) {
572 + cache_chart_generated = 1;
573 +
574 + printf("CHART %s.%s '' 'Cache operations' 'operations/s' %s '' line %d %d %s\n"
575 + , RRD_TYPE_PERF
576 + , "cache"
577 + , RRD_FAMILY_HW
578 + , NETDATA_CHART_PRIO_PERF_CACHE
579 + , update_every
580 + , PLUGIN_PERF_NAME
581 + );
582 + printf("DIMENSION %s '' absolute 1 1\n", "references");
583 + printf("DIMENSION %s '' absolute 1 1\n", "misses");
584 + }
585 +
586 + printf(
587 + "BEGIN %s.%s\n"
588 + , RRD_TYPE_PERF
589 + , "cache"
590 + );
591 + if(likely(perf_events[EV_ID_CACHE_REFERENCES].updated)) {
592 + printf(
593 + "SET %s = %lld\n"
594 + , "references"
595 + , (collected_number) perf_events[EV_ID_CACHE_REFERENCES].value
596 + );
597 + }
598 + if(likely(perf_events[EV_ID_CACHE_MISSES].updated)) {
599 + printf(
600 + "SET %s = %lld\n"
601 + , "misses"
602 + , (collected_number) perf_events[EV_ID_CACHE_MISSES].value
603 + );
604 + }
605 + printf("END\n");
606 + }
607 +
608 + // ------------------------------------------------------------------------
609 +
610 + if(likely(perf_events[EV_ID_BUS_CYCLES].updated)) {
611 + if(unlikely(!bus_cycles_chart_generated)) {
612 + bus_cycles_chart_generated = 1;
613 +
614 + printf("CHART %s.%s '' 'Bus cycles' 'cycles/s' %s '' line %d %d %s\n"
615 + , RRD_TYPE_PERF
616 + , "bus_cycles"
617 + , RRD_FAMILY_HW
618 + , NETDATA_CHART_PRIO_PERF_BUS_CYCLES
619 + , update_every
620 + , PLUGIN_PERF_NAME
621 + );
622 + printf("DIMENSION %s '' absolute 1 1\n", "bus");
623 + }
624 +
625 + printf(
626 + "BEGIN %s.%s\n"
627 + , RRD_TYPE_PERF
628 + , "bus_cycles"
629 + );
630 + printf(
631 + "SET %s = %lld\n"
632 + , "bus"
633 + , (collected_number) perf_events[EV_ID_BUS_CYCLES].value
634 + );
635 + printf("END\n");
636 + }
637 +
638 + // ------------------------------------------------------------------------
639 +
640 + if(likely(perf_events[EV_ID_STALLED_CYCLES_FRONTEND].updated || perf_events[EV_ID_STALLED_CYCLES_BACKEND].updated)) {
641 + if(unlikely(!stalled_cycles_chart_generated)) {
642 + stalled_cycles_chart_generated = 1;
643 +
644 + printf("CHART %s.%s '' 'Stalled frontend and backend cycles' 'cycles/s' %s '' line %d %d %s\n"
645 + , RRD_TYPE_PERF
646 + , "stalled_cycles"
647 + , RRD_FAMILY_HW
648 + , NETDATA_CHART_PRIO_PERF_FRONT_BACK_CYCLES
649 + , update_every
650 + , PLUGIN_PERF_NAME
651 + );
652 + printf("DIMENSION %s '' absolute 1 1\n", "frontend");
653 + printf("DIMENSION %s '' absolute 1 1\n", "backend");
654 + }
655 +
656 + printf(
657 + "BEGIN %s.%s\n"
658 + , RRD_TYPE_PERF
659 + , "stalled_cycles"
660 + );
661 + if(likely(perf_events[EV_ID_STALLED_CYCLES_FRONTEND].updated)) {
662 + printf(
663 + "SET %s = %lld\n"
664 + , "frontend"
665 + , (collected_number) perf_events[EV_ID_STALLED_CYCLES_FRONTEND].value
666 + );
667 + }
668 + if(likely(perf_events[EV_ID_STALLED_CYCLES_BACKEND].updated)) {
669 + printf(
670 + "SET %s = %lld\n"
671 + , "backend"
672 + , (collected_number) perf_events[EV_ID_STALLED_CYCLES_BACKEND].value
673 + );
674 + }
675 + printf("END\n");
676 + }
677 +
678 + // ------------------------------------------------------------------------
679 +
680 + if(likely(perf_events[EV_ID_CPU_MIGRATIONS].updated)) {
681 + if(unlikely(!migrations_chart_generated)) {
682 + migrations_chart_generated = 1;
683 +
684 + printf("CHART %s.%s '' 'CPU migrations' 'migrations' %s '' line %d %d %s\n"
685 + , RRD_TYPE_PERF
686 + , "migrations"
687 + , RRD_FAMILY_SW
688 + , NETDATA_CHART_PRIO_PERF_MIGRATIONS
689 + , update_every
690 + , PLUGIN_PERF_NAME
691 + );
692 + printf("DIMENSION %s '' absolute 1 1\n", "migrations");
693 + }
694 +
695 + printf(
696 + "BEGIN %s.%s\n"
697 + , RRD_TYPE_PERF
698 + , "migrations"
699 + );
700 + printf(
701 + "SET %s = %lld\n"
702 + , "migrations"
703 + , (collected_number) perf_events[EV_ID_CPU_MIGRATIONS].value
704 + );
705 + printf("END\n");
706 + }
707 +
708 + // ------------------------------------------------------------------------
709 +
710 + if(likely(perf_events[EV_ID_ALIGNMENT_FAULTS].updated)) {
711 + if(unlikely(!alighnment_chart_generated)) {
712 + alighnment_chart_generated = 1;
713 +
714 + printf("CHART %s.%s '' 'Alighnment faults' 'faults' %s '' line %d %d %s\n"
715 + , RRD_TYPE_PERF
716 + , "alighnment_faults"
717 + , RRD_FAMILY_SW
718 + , NETDATA_CHART_PRIO_PERF_ALIGNMENT
719 + , update_every
720 + , PLUGIN_PERF_NAME
721 + );
722 + printf("DIMENSION %s '' absolute 1 1\n", "faults");
723 + }
724 +
725 + printf(
726 + "BEGIN %s.%s\n"
727 + , RRD_TYPE_PERF
728 + , "alighnment_faults"
729 + );
730 + printf(
731 + "SET %s = %lld\n"
732 + , "faults"
733 + , (collected_number) perf_events[EV_ID_ALIGNMENT_FAULTS].value
734 + );
735 + printf("END\n");
736 + }
737 +
738 + // ------------------------------------------------------------------------
739 +
740 + if(likely(perf_events[EV_ID_EMULATION_FAULTS].updated)) {
741 + if(unlikely(!emulation_chart_generated)) {
742 + emulation_chart_generated = 1;
743 +
744 + printf("CHART %s.%s '' 'Emulation faults' 'faults' %s '' line %d %d %s\n"
745 + , RRD_TYPE_PERF
746 + , "emulation_faults"
747 + , RRD_FAMILY_SW
748 + , NETDATA_CHART_PRIO_PERF_EMULATION
749 + , update_every
750 + , PLUGIN_PERF_NAME
751 + );
752 + printf("DIMENSION %s '' absolute 1 1\n", "faults");
753 + }
754 +
755 + printf(
756 + "BEGIN %s.%s\n"
757 + , RRD_TYPE_PERF
758 + , "emulation_faults"
759 + );
760 + printf(
761 + "SET %s = %lld\n"
762 + , "faults"
763 + , (collected_number) perf_events[EV_ID_EMULATION_FAULTS].value
764 + );
765 + printf("END\n");
766 + }
767 +
768 + // ------------------------------------------------------------------------
769 +
770 + if(likely(perf_events[EV_ID_L1D_READ_ACCESS].updated || perf_events[EV_ID_L1D_READ_MISS].updated
771 + || perf_events[EV_ID_L1D_WRITE_ACCESS].updated || perf_events[EV_ID_L1D_WRITE_MISS].updated)) {
772 + if(unlikely(!L1D_chart_generated)) {
773 + L1D_chart_generated = 1;
774 +
775 + printf("CHART %s.%s '' 'L1D cache operations' 'events/s' %s '' line %d %d %s\n"
776 + , RRD_TYPE_PERF
777 + , "l1d_cache"
778 + , RRD_FAMILY_CACHE
779 + , NETDATA_CHART_PRIO_PERF_L1D
780 + , update_every
781 + , PLUGIN_PERF_NAME
782 + );
783 + printf("DIMENSION %s '' absolute 1 1\n", "read_access");
784 + printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
785 + printf("DIMENSION %s '' absolute -1 1\n", "write_access");
786 + printf("DIMENSION %s '' absolute -1 1\n", "write_misses");
787 + }
788 +
789 + printf(
790 + "BEGIN %s.%s\n"
791 + , RRD_TYPE_PERF
792 + , "l1d_cache"
793 + );
794 + if(likely(perf_events[EV_ID_L1D_READ_ACCESS].updated)) {
795 + printf(
796 + "SET %s = %lld\n"
797 + , "read_access"
798 + , (collected_number) perf_events[EV_ID_L1D_READ_ACCESS].value
799 + );
800 + }
801 + if(likely(perf_events[EV_ID_L1D_READ_MISS].updated)) {
802 + printf(
803 + "SET %s = %lld\n"
804 + , "read_misses"
805 + , (collected_number) perf_events[EV_ID_L1D_READ_MISS].value
806 + );
807 + }
808 + if(likely(perf_events[EV_ID_L1D_WRITE_ACCESS].updated)) {
809 + printf(
810 + "SET %s = %lld\n"
811 + , "write_access"
812 + , (collected_number) perf_events[EV_ID_L1D_WRITE_ACCESS].value
813 + );
814 + }
815 + if(likely(perf_events[EV_ID_L1D_WRITE_MISS].updated)) {
816 + printf(
817 + "SET %s = %lld\n"
818 + , "write_misses"
819 + , (collected_number) perf_events[EV_ID_L1D_WRITE_MISS].value
820 + );
821 + }
822 + printf("END\n");
823 + }
824 +
825 + // ------------------------------------------------------------------------
826 +
827 + if(likely(perf_events[EV_ID_L1D_PREFETCH_ACCESS].updated)) {
828 + if(unlikely(!L1D_prefetch_chart_generated)) {
829 + L1D_prefetch_chart_generated = 1;
830 +
831 + printf("CHART %s.%s '' 'L1D prefetch cache operations' 'prefetches/s' %s '' line %d %d %s\n"
832 + , RRD_TYPE_PERF
833 + , "l1d_cache_prefetch"
834 + , RRD_FAMILY_CACHE
835 + , NETDATA_CHART_PRIO_PERF_L1D_PREFETCH
836 + , update_every
837 + , PLUGIN_PERF_NAME
838 + );
839 + printf("DIMENSION %s '' absolute 1 1\n", "prefetches");
840 + }
841 +
842 + printf(
843 + "BEGIN %s.%s\n"
844 + , RRD_TYPE_PERF
845 + , "l1d_cache_prefetch"
846 + );
847 + printf(
848 + "SET %s = %lld\n"
849 + , "prefetches"
850 + , (collected_number) perf_events[EV_ID_L1D_PREFETCH_ACCESS].value
851 + );
852 + printf("END\n");
853 + }
854 +
855 + // ------------------------------------------------------------------------
856 +
857 + if(likely(perf_events[EV_ID_L1I_READ_ACCESS].updated || perf_events[EV_ID_L1I_READ_MISS].updated)) {
858 + if(unlikely(!L1I_chart_generated)) {
859 + L1I_chart_generated = 1;
860 +
861 + printf("CHART %s.%s '' 'L1I cache operations' 'events/s' %s '' line %d %d %s\n"
862 + , RRD_TYPE_PERF
863 + , "l1i_cache"
864 + , RRD_FAMILY_CACHE
865 + , NETDATA_CHART_PRIO_PERF_L1I
866 + , update_every
867 + , PLUGIN_PERF_NAME
868 + );
869 + printf("DIMENSION %s '' absolute 1 1\n", "read_access");
870 + printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
871 + }
872 +
873 + printf(
874 + "BEGIN %s.%s\n"
875 + , RRD_TYPE_PERF
876 + , "l1i_cache"
877 + );
878 + if(likely(perf_events[EV_ID_L1I_READ_ACCESS].updated)) {
879 + printf(
880 + "SET %s = %lld\n"
881 + , "read_access"
882 + , (collected_number) perf_events[EV_ID_L1I_READ_ACCESS].value
883 + );
884 + }
885 + if(likely(perf_events[EV_ID_L1I_READ_MISS].updated)) {
886 + printf(
887 + "SET %s = %lld\n"
888 + , "read_misses"
889 + , (collected_number) perf_events[EV_ID_L1I_READ_MISS].value
890 + );
891 + }
892 + printf("END\n");
893 + }
894 +
895 + // ------------------------------------------------------------------------
896 +
897 + if(likely(perf_events[EV_ID_LL_READ_ACCESS].updated || perf_events[EV_ID_LL_READ_MISS].updated
898 + || perf_events[EV_ID_LL_WRITE_ACCESS].updated || perf_events[EV_ID_LL_WRITE_MISS].updated)) {
899 + if(unlikely(!LL_chart_generated)) {
900 + LL_chart_generated = 1;
901 +
902 + printf("CHART %s.%s '' 'LL cache operations' 'events/s' %s '' line %d %d %s\n"
903 + , RRD_TYPE_PERF
904 + , "ll_cache"
905 + , RRD_FAMILY_CACHE
906 + , NETDATA_CHART_PRIO_PERF_LL
907 + , update_every
908 + , PLUGIN_PERF_NAME
909 + );
910 + printf("DIMENSION %s '' absolute 1 1\n", "read_access");
911 + printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
912 + printf("DIMENSION %s '' absolute -1 1\n", "write_access");
913 + printf("DIMENSION %s '' absolute -1 1\n", "write_misses");
914 + }
915 +
916 + printf(
917 + "BEGIN %s.%s\n"
918 + , RRD_TYPE_PERF
919 + , "ll_cache"
920 + );
921 + if(likely(perf_events[EV_ID_LL_READ_ACCESS].updated)) {
922 + printf(
923 + "SET %s = %lld\n"
924 + , "read_access"
925 + , (collected_number) perf_events[EV_ID_LL_READ_ACCESS].value
926 + );
927 + }
928 + if(likely(perf_events[EV_ID_LL_READ_MISS].updated)) {
929 + printf(
930 + "SET %s = %lld\n"
931 + , "read_misses"
932 + , (collected_number) perf_events[EV_ID_LL_READ_MISS].value
933 + );
934 + }
935 + if(likely(perf_events[EV_ID_LL_WRITE_ACCESS].updated)) {
936 + printf(
937 + "SET %s = %lld\n"
938 + , "write_access"
939 + , (collected_number) perf_events[EV_ID_LL_WRITE_ACCESS].value
940 + );
941 + }
942 + if(likely(perf_events[EV_ID_LL_WRITE_MISS].updated)) {
943 + printf(
944 + "SET %s = %lld\n"
945 + , "write_misses"
946 + , (collected_number) perf_events[EV_ID_LL_WRITE_MISS].value
947 + );
948 + }
949 + printf("END\n");
950 + }
951 +
952 + // ------------------------------------------------------------------------
953 +
954 + if(likely(perf_events[EV_ID_DTLB_READ_ACCESS].updated || perf_events[EV_ID_DTLB_READ_MISS].updated
955 + || perf_events[EV_ID_DTLB_WRITE_ACCESS].updated || perf_events[EV_ID_DTLB_WRITE_MISS].updated)) {
956 + if(unlikely(!DTLB_chart_generated)) {
957 + DTLB_chart_generated = 1;
958 +
959 + printf("CHART %s.%s '' 'DTLB cache operations' 'events/s' %s '' line %d %d %s\n"
960 + , RRD_TYPE_PERF
961 + , "dtlb_cache"
962 + , RRD_FAMILY_CACHE
963 + , NETDATA_CHART_PRIO_PERF_DTLB
964 + , update_every
965 + , PLUGIN_PERF_NAME
966 + );
967 + printf("DIMENSION %s '' absolute 1 1\n", "read_access");
968 + printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
969 + printf("DIMENSION %s '' absolute -1 1\n", "write_access");
970 + printf("DIMENSION %s '' absolute -1 1\n", "write_misses");
971 + }
972 +
973 + printf(
974 + "BEGIN %s.%s\n"
975 + , RRD_TYPE_PERF
976 + , "dtlb_cache"
977 + );
978 + if(likely(perf_events[EV_ID_DTLB_READ_ACCESS].updated)) {
979 + printf(
980 + "SET %s = %lld\n"
981 + , "read_access"
982 + , (collected_number) perf_events[EV_ID_DTLB_READ_ACCESS].value
983 + );
984 + }
985 + if(likely(perf_events[EV_ID_DTLB_READ_MISS].updated)) {
986 + printf(
987 + "SET %s = %lld\n"
988 + , "read_misses"
989 + , (collected_number) perf_events[EV_ID_DTLB_READ_MISS].value
990 + );
991 + }
992 + if(likely(perf_events[EV_ID_DTLB_WRITE_ACCESS].updated)) {
993 + printf(
994 + "SET %s = %lld\n"
995 + , "write_access"
996 + , (collected_number) perf_events[EV_ID_DTLB_WRITE_ACCESS].value
997 + );
998 + }
999 + if(likely(perf_events[EV_ID_DTLB_WRITE_MISS].updated)) {
1000 + printf(
1001 + "SET %s = %lld\n"
1002 + , "write_misses"
1003 + , (collected_number) perf_events[EV_ID_DTLB_WRITE_MISS].value
1004 + );
1005 + }
1006 + printf("END\n");
1007 + }
1008 +
1009 + // ------------------------------------------------------------------------
1010 +
1011 + if(likely(perf_events[EV_ID_ITLB_READ_ACCESS].updated || perf_events[EV_ID_ITLB_READ_MISS].updated)) {
1012 + if(unlikely(!ITLB_chart_generated)) {
1013 + ITLB_chart_generated = 1;
1014 +
1015 + printf("CHART %s.%s '' 'ITLB cache operations' 'events/s' %s '' line %d %d %s\n"
1016 + , RRD_TYPE_PERF
1017 + , "itlb_cache"
1018 + , RRD_FAMILY_CACHE
1019 + , NETDATA_CHART_PRIO_PERF_ITLB
1020 + , update_every
1021 + , PLUGIN_PERF_NAME
1022 + );
1023 + printf("DIMENSION %s '' absolute 1 1\n", "read_access");
1024 + printf("DIMENSION %s '' absolute 1 1\n", "read_misses");
1025 + }
1026 +
1027 + printf(
1028 + "BEGIN %s.%s\n"
1029 + , RRD_TYPE_PERF
1030 + , "itlb_cache"
1031 + );
1032 + if(likely(perf_events[EV_ID_ITLB_READ_ACCESS].updated)) {
1033 + printf(
1034 + "SET %s = %lld\n"
1035 + , "read_access"
1036 + , (collected_number) perf_events[EV_ID_ITLB_READ_ACCESS].value
1037 + );
1038 + }
1039 + if(likely(perf_events[EV_ID_ITLB_READ_MISS].updated)) {
1040 + printf(
1041 + "SET %s = %lld\n"
1042 + , "read_misses"
1043 + , (collected_number) perf_events[EV_ID_ITLB_READ_MISS].value
1044 + );
1045 + }
1046 + printf("END\n");
1047 + }
1048 +
1049 + // ------------------------------------------------------------------------
1050 +
1051 + if(likely(perf_events[EV_ID_PBU_READ_ACCESS].updated)) {
1052 + if(unlikely(!PBU_chart_generated)) {
1053 + PBU_chart_generated = 1;
1054 +
1055 + printf("CHART %s.%s '' 'PBU cache operations' 'events/s' %s '' line %d %d %s\n"
1056 + , RRD_TYPE_PERF
1057 + , "pbu_cache"
1058 + , RRD_FAMILY_CACHE
1059 + , NETDATA_CHART_PRIO_PERF_PBU
1060 + , update_every
1061 + , PLUGIN_PERF_NAME
1062 + );
1063 + printf("DIMENSION %s '' absolute 1 1\n", "read_access");
1064 + }
1065 +
1066 + printf(
1067 + "BEGIN %s.%s\n"
1068 + , RRD_TYPE_PERF
1069 + , "pbu_cache"
1070 + );
1071 + printf(
1072 + "SET %s = %lld\n"
1073 + , "read_access"
1074 + , (collected_number) perf_events[EV_ID_PBU_READ_ACCESS].value
1075 + );
1076 + printf("END\n");
1077 + }
1078 +}
1079 +
1080 +void parse_command_line(int argc, char **argv) {
1081 + int i, plugin_enabled = 0;
1082 +
1083 + for(i = 1; i < argc ; i++) {
1084 + if(isdigit(*argv[i]) && !freq) {
1085 + int n = str2i(argv[i]);
1086 + if(n > 0 && n < 86400) {
1087 + freq = n;
1088 + continue;
1089 + }
1090 + }
1091 + 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) {
1092 + printf("perf.plugin %s\n", VERSION);
1093 + exit(0);
1094 + }
1095 + else if(strcmp("all", argv[i]) == 0) {
1096 + struct perf_event *current_event = NULL;
1097 +
1098 + for(current_event = &perf_events[0]; current_event->id != EV_ID_END; current_event++)
1099 + current_event->disabled = 0;
1100 +
1101 + plugin_enabled = 1;
1102 + continue;
1103 + }
1104 + else if(strcmp("cycles", argv[i]) == 0) {
1105 + perf_events[EV_ID_CPU_CYCLES].disabled = 0;
1106 + perf_events[EV_ID_REF_CPU_CYCLES].disabled = 0;
1107 + plugin_enabled = 1;
1108 + continue;
1109 + }
1110 + else if(strcmp("instructions", argv[i]) == 0) {
1111 + perf_events[EV_ID_INSTRUCTIONS].disabled = 0;
1112 + plugin_enabled = 1;
1113 + continue;
1114 + }
1115 + else if(strcmp("branch", argv[i]) == 0) {
1116 + perf_events[EV_ID_BRANCH_INSTRUCTIONS].disabled = 0;
1117 + perf_events[EV_ID_BRANCH_MISSES].disabled = 0;
1118 + plugin_enabled = 1;
1119 + continue;
1120 + }
1121 + else if(strcmp("cache", argv[i]) == 0) {
1122 + perf_events[EV_ID_CACHE_REFERENCES].disabled = 0;
1123 + perf_events[EV_ID_CACHE_MISSES].disabled = 0;
1124 + plugin_enabled = 1;
1125 + continue;
1126 + }
1127 + else if(strcmp("bus", argv[i]) == 0) {
1128 + perf_events[EV_ID_BUS_CYCLES].disabled = 0;
1129 + plugin_enabled = 1;
1130 + continue;
1131 + }
1132 + else if(strcmp("stalled", argv[i]) == 0) {
1133 + perf_events[EV_ID_STALLED_CYCLES_FRONTEND].disabled = 0;
1134 + perf_events[EV_ID_STALLED_CYCLES_BACKEND].disabled = 0;
1135 + plugin_enabled = 1;
1136 + continue;
1137 + }
1138 + else if(strcmp("migrations", argv[i]) == 0) {
1139 + perf_events[EV_ID_CPU_MIGRATIONS].disabled = 0;
1140 + plugin_enabled = 1;
1141 + continue;
1142 + }
1143 + else if(strcmp("alighnment", argv[i]) == 0) {
1144 + perf_events[EV_ID_ALIGNMENT_FAULTS].disabled = 0;
1145 + plugin_enabled = 1;
1146 + continue;
1147 + }
1148 + else if(strcmp("emulation", argv[i]) == 0) {
1149 + perf_events[EV_ID_EMULATION_FAULTS].disabled = 0;
1150 + plugin_enabled = 1;
1151 + continue;
1152 + }
1153 + else if(strcmp("L1D", argv[i]) == 0) {
1154 + perf_events[EV_ID_L1D_READ_ACCESS].disabled = 0;
1155 + perf_events[EV_ID_L1D_READ_MISS].disabled = 0;
1156 + perf_events[EV_ID_L1D_WRITE_ACCESS].disabled = 0;
1157 + perf_events[EV_ID_L1D_WRITE_MISS].disabled = 0;
1158 + plugin_enabled = 1;
1159 + continue;
1160 + }
1161 + else if(strcmp("L1D-prefetch", argv[i]) == 0) {
1162 + perf_events[EV_ID_L1D_PREFETCH_ACCESS].disabled = 0;
1163 + plugin_enabled = 1;
1164 + continue;
1165 + }
1166 + else if(strcmp("L1I", argv[i]) == 0) {
1167 + perf_events[EV_ID_L1I_READ_ACCESS].disabled = 0;
1168 + perf_events[EV_ID_L1I_READ_MISS].disabled = 0;
1169 + plugin_enabled = 1;
1170 + continue;
1171 + }
1172 + else if(strcmp("LL", argv[i]) == 0) {
1173 + perf_events[EV_ID_LL_READ_ACCESS].disabled = 0;
1174 + perf_events[EV_ID_LL_READ_MISS].disabled = 0;
1175 + perf_events[EV_ID_LL_WRITE_ACCESS].disabled = 0;
1176 + perf_events[EV_ID_LL_WRITE_MISS].disabled = 0;
1177 + plugin_enabled = 1;
1178 + continue;
1179 + }
1180 + else if(strcmp("DTLB", argv[i]) == 0) {
1181 + perf_events[EV_ID_DTLB_READ_ACCESS].disabled = 0;
1182 + perf_events[EV_ID_DTLB_READ_MISS].disabled = 0;
1183 + perf_events[EV_ID_DTLB_WRITE_ACCESS].disabled = 0;
1184 + perf_events[EV_ID_DTLB_WRITE_MISS].disabled = 0;
1185 + plugin_enabled = 1;
1186 + continue;
1187 + }
1188 + else if(strcmp("ITLB", argv[i]) == 0) {
1189 + perf_events[EV_ID_ITLB_READ_ACCESS].disabled = 0;
1190 + perf_events[EV_ID_ITLB_READ_MISS].disabled = 0;
1191 + plugin_enabled = 1;
1192 + continue;
1193 + }
1194 + else if(strcmp("PBU", argv[i]) == 0) {
1195 + perf_events[EV_ID_PBU_READ_ACCESS].disabled = 0;
1196 + plugin_enabled = 1;
1197 + continue;
1198 + }
1199 + else if(strcmp("debug", argv[i]) == 0) {
1200 + debug = 1;
1201 + continue;
1202 + }
1203 + else if(strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
1204 + fprintf(stderr,
1205 + "\n"
1206 + " netdata perf.plugin %s\n"
1207 + " Copyright (C) 2019 Netdata Inc.\n"
1208 + " Released under GNU General Public License v3 or later.\n"
1209 + " All rights reserved.\n"
1210 + "\n"
1211 + " This program is a data collector plugin for netdata.\n"
1212 + "\n"
1213 + " Available command line options:\n"
1214 + "\n"
1215 + " COLLECTION_FREQUENCY data collection frequency in seconds\n"
1216 + " minimum: %d\n"
1217 + "\n"
1218 + " all enable all charts\n"
1219 + "\n"
1220 + " cycles enable CPU cycles chart\n"
1221 + "\n"
1222 + " instructions enable Instructions chart\n"
1223 + "\n"
1224 + " branch enable Branch instructions chart\n"
1225 + "\n"
1226 + " cache enable Cache operations chart\n"
1227 + "\n"
1228 + " bus enable Bus cycles chart\n"
1229 + "\n"
1230 + " stalled enable Stalled frontend and backend cycles chart\n"
1231 + "\n"
1232 + " migrations enable CPU migrations chart\n"
1233 + "\n"
1234 + " alighnment enable Alignment faults chart\n"
1235 + "\n"
1236 + " emulation enable Emulation faults chart\n"
1237 + "\n"
1238 + " L1D enable L1D cache operations chart\n"
1239 + "\n"
1240 + " L1D-prefetch enable L1D prefetch cache operations chart\n"
1241 + "\n"
1242 + " L1I enable L1I cache operations chart\n"
1243 + "\n"
1244 + " LL enable LL cache operations chart\n"
1245 + "\n"
1246 + " DTLB enable DTLB cache operations chart\n"
1247 + "\n"
1248 + " ITLB enable ITLB cache operations chart\n"
1249 + "\n"
1250 + " PBU enable PBU cache operations chart\n"
1251 + "\n"
1252 + " debug enable verbose output\n"
1253 + " default: disabled\n"
1254 + "\n"
1255 + " -v\n"
1256 + " -V\n"
1257 + " --version print version and exit\n"
1258 + "\n"
1259 + " -h\n"
1260 + " --help print this message and exit\n"
1261 + "\n"
1262 + " For more information:\n"
1263 + " https://github.com/netdata/netdata/tree/master/collectors/perf.plugin\n"
1264 + "\n"
1265 + , VERSION
1266 + , update_every
1267 + );
1268 + exit(1);
1269 + }
1270 +
1271 + error("ignoring parameter '%s'", argv[i]);
1272 + }
1273 +
1274 + if(!plugin_enabled){
1275 + info("no charts enabled - nothing to do.");
1276 + printf("DISABLE\n");
1277 + exit(1);
1278 + }
1279 +}
1280 +
1281 +int main(int argc, char **argv) {
1282 +
1283 + // ------------------------------------------------------------------------
1284 + // initialization of netdata plugin
1285 +
1286 + program_name = "perf.plugin";
1287 +
1288 + // disable syslog
1289 + error_log_syslog = 0;
1290 +
1291 + // set errors flood protection to 100 logs per hour
1292 + error_log_errors_per_period = 100;
1293 + error_log_throttle_period = 3600;
1294 +
1295 + parse_command_line(argc, argv);
1296 +
1297 + errno = 0;
1298 +
1299 + if(freq >= update_every)
1300 + update_every = freq;
1301 + else if(freq)
1302 + error("update frequency %d seconds is too small for PERF. Using %d.", freq, update_every);
1303 +
1304 + if(unlikely(debug)) fprintf(stderr, "perf.plugin: calling perf_init()\n");
1305 + int perf = !perf_init();
1306 +
1307 + // ------------------------------------------------------------------------
1308 + // the main loop
1309 +
1310 + if(unlikely(debug)) fprintf(stderr, "perf.plugin: starting data collection\n");
1311 +
1312 + time_t started_t = now_monotonic_sec();
1313 +
1314 + size_t iteration;
1315 + usec_t step = update_every * USEC_PER_SEC;
1316 +
1317 + heartbeat_t hb;
1318 + heartbeat_init(&hb);
1319 + for(iteration = 0; 1; iteration++) {
1320 + usec_t dt = heartbeat_next(&hb, step);
1321 +
1322 + if(unlikely(netdata_exit)) break;
1323 +
1324 + if(unlikely(debug && iteration))
1325 + fprintf(stderr, "perf.plugin: iteration %zu, dt %llu usec\n"
1326 + , iteration
1327 + , dt
1328 + );
1329 +
1330 + if(likely(perf)) {
1331 + if(unlikely(debug)) fprintf(stderr, "perf.plugin: calling perf_collect()\n");
1332 + perf = !perf_collect();
1333 +
1334 + if(likely(perf)) {
1335 + if(unlikely(debug)) fprintf(stderr, "perf.plugin: calling perf_send_metrics()\n");
1336 + perf_send_metrics();
1337 + }
1338 + }
1339 +
1340 + fflush(stdout);
1341 +
1342 + // restart check (14400 seconds)
1343 + if(now_monotonic_sec() - started_t > 14400) break;
1344 + }
1345 +
1346 + info("process exiting");
1347 + perf_free();
1348 +}
collectors/plugins.d/README.md
+1
@@ -15,6 +15,7 @@ plugin|language|O/S|description
15 [freeipmi.plugin](../freeipmi.plugin/)|`C`|linux|collects metrics from enterprise hardware sensors, on Linux servers.
16 [nfacct.plugin](../nfacct.plugin/)|`C`|linux|collects netfilter firewall, connection tracker and accounting metrics using `libmnl` and `libnetfilter_acct`.
17 [xenstat.plugin](../xenstat.plugin/)|`C`|linux|collects XenServer and XCP-ng metrics using `lxenstat`.
18 +[perf.plugin](../perf.plugin/)|`C`|linux|collects CPU performance metrics using performance monitoring units (PMU).
19 [node.d.plugin](../node.d.plugin/)|`node.js`|all|a **plugin orchestrator** for data collection modules written in `node.js`.
20 [python.d.plugin](../python.d.plugin/)|`python`|all|a **plugin orchestrator** for data collection modules written in `python` v2 or v3 (both are supported).
21
configure.ac
+14
@@ -685,6 +685,19 @@ AC_MSG_RESULT([${enable_plugin_xenstat}])
685 AM_CONDITIONAL([ENABLE_PLUGIN_XENSTAT], [test "${enable_plugin_xenstat}" = "yes"])
686
687
688 +# -----------------------------------------------------------------------------
689 +# perf.plugin
690 +
691 +AC_MSG_CHECKING([if perf.plugin should be enabled])
692 +if test "${build_target}" == "linux" ; then
693 + enable_plugin_perf="yes"
694 +else
695 + enable_plugin_perf="no"
696 +fi
697 +AC_MSG_RESULT([${enable_plugin_perf}])
698 +AM_CONDITIONAL([ENABLE_PLUGIN_PERF], [test "${enable_plugin_perf}" = "yes"])
699 +
700 +
701 # -----------------------------------------------------------------------------
702 # AWS Kinesis backend - libaws-cpp-sdk-kinesis, libaws-cpp-sdk-core, libssl, libcrypto, libcurl
703
@@ -999,6 +1012,7 @@ AC_CONFIG_FILES([
1012 collectors/statsd.plugin/Makefile
1013 collectors/tc.plugin/Makefile
1014 collectors/xenstat.plugin/Makefile
1015 + collectors/perf.plugin/Makefile
1016 daemon/Makefile
1017 database/Makefile
1018 database/engine/Makefile
docs/Add-more-charts-to-netdata.md
+6 -1
@@ -69,6 +69,7 @@ To control which plugins Netdata run, edit `netdata.conf` and check the `[plugin
69 # charts.d = yes
70 # apps = yes
71 # xenstat = yes
72 + # perf = no
73 ```
74
75 The default for all plugins is the option `enable running new plugins`. So, setting this to `no` will disable all the plugins, except the ones specifically enabled.
@@ -95,7 +96,7 @@ sudo su -s /bin/bash netdata
96 ```
97
98 Similarly, you can use `charts.d.plugin` for BASH plugins and `node.d.plugin` for node.js plugins.
98 -Other plugins (like `apps.plugin`, `freeipmi.plugin`, `fping.plugin`, `ioping.plugin`) use the native Netdata plugin API and can be run directly.
99 +Other plugins (like `apps.plugin`, `freeipmi.plugin`, `fping.plugin`, `ioping.plugin`, `nfacct.plugin`, `xenstat.plugin`, `perf.plugin`) use the native Netdata plugin API and can be run directly.
100
101 If you need to configure a Netdata plugin or module, all user supplied configuration is kept at `/etc/netdata` while the stock versions of all files is at `/usr/lib/netdata/conf.d`.
102 To copy a stock file and edit it, run `/etc/netdata/edit-config`. Running this command without an argument, will list the available stock files.
@@ -116,6 +117,9 @@ plugin | language | plugin<br/>configuration | modules<br/>configuration |
117 `fping.plugin`<br/>(external plugin for collecting network latencies)|`C`|`fping.conf`|This plugin is a wrapper for the `fping` command.
118 `ioping.plugin`<br/>(external plugin for collecting disk latencies)|`C`|`ioping.conf`|This plugin is a wrapper for the `ioping` command.
119 `freeipmi.plugin`<br/>(external plugin for collecting IPMI h/w sensors)|`C`|`netdata.conf` section `[plugin:freeipmi]`
120 +`nfacct.plugin`<br/>(external plugin for monitoring netfilter firewall and connection tracker)|`C`|`netdata.conf` section `[plugin:nfacct]`|N/A
121 +`xenstat.plugin`<br/>(external plugin for monitoring XCP-ng and XenServer)|`C`|`netdata.conf` section `[plugin:xenstat]`|N/A
122 +`perf.plugin`<br/>(external plugin for monitoring CPU performance on Linux)|`C`|`netdata.conf` section `[plugin:perf]`|N/A
123 `idlejitter.plugin`<br/>(internal plugin for monitoring CPU jitter)|`C`|N/A|N/A
124 `macos.plugin`<br/>(internal plugin for monitoring MacOS system resources)|`C`|`netdata.conf` section `[plugin:macos]`|one section for each module `[plugin:macos:MODULE]`. Each module may provide additional sections in the form of `[plugin:macos:MODULE:SUBSECTION]`.
125 `node.d.plugin`<br/>(external plugin orchestrator of node.js modules)|`node.js`|`node.d.conf`|a file for each module in `/etc/netdata/node.d/`.
@@ -321,6 +325,7 @@ application|language|notes|
325 :---------:|:------:|:----|
326 apps|C|`apps.plugin` collects resource usage statistics for all processes running in the system. It groups the entire process tree and reports dozens of metrics for CPU utilization, memory footprint, disk I/O, swap memory, network connections, open files and sockets, etc. It reports metrics for application groups, users and user groups.<br/>&nbsp;<br/>[Documentation of `apps.plugin`](../collectors/apps.plugin/).<br/>&nbsp;<br/>Netdata plugin: [`apps_plugin.c`](../collectors/apps.plugin)<br/>configuration file: [`apps_groups.conf`](../collectors/apps.plugin)|
327 ioping|C|Charts disk latency statistics for a directory/file/device, using the `ioping` command. A recent (probably unreleased) version of ioping is required. The plugin supplied can install it in `/usr/local`.<br/>&nbsp;<br/>Netdata plugin: [ioping.plugin](../collectors/ioping.plugin) (this is a shell wrapper to start ioping - once ioping is started, Netdata and ioping communicate directly - it can also install the right version of ioping)<br/>configuration file: [ioping.conf](../collectors/ioping.plugin)|
328 +perf|C|`perf.plugin` collects CPU performance metrics using hardware performance monitoring units (PMU).<br/>&nbsp;<br/>[Documentation of `perf.plugin`](../collectors/perf.plugin/).<br/>&nbsp;<br/>Netdata plugin: [`perf_plugin.c`](../collectors/perf.plugin)|
329 cpu_apps|BASH<br/>Shell Script|Collects the CPU utilization of select apps.<br/><br/>DEPRECATED IN FAVOR OF `apps.plugin`. It is still supplied only as an example module to shell scripting plugins.<br/>&nbsp;<br/>Netdata plugin: [charts.d.plugin](../collectors/charts.d.plugin#chartsdplugin)<br/>plugin module: [cpu_apps.chart.sh](../collectors/charts.d.plugin/cpu_apps)<br/>configuration file: [charts.d/cpu_apps.conf](../collectors/charts.d.plugin/cpu_apps)|
330 load_average|BASH<br/>Shell Script|Collects the current system load average.<br/><br/>DEPRECATED IN FAVOR OF THE NETDATA INTERNAL ONE. It is still supplied only as an example module to shell scripting plugins.<br/>&nbsp;<br/>Netdata plugin: [charts.d.plugin](../collectors/charts.d.plugin#chartsdplugin)<br/>plugin module: [load_average.chart.sh](../collectors/charts.d.plugin/load_average)<br/>configuration file: [charts.d/load_average.conf](../collectors/charts.d.plugin/load_average)|
331 mem_apps|BASH<br/>Shell Script|Collects the memory footprint of select applications.<br/><br/>DEPRECATED IN FAVOR OF `apps.plugin`. It is still supplied only as an example module to shell scripting plugins.<br/>&nbsp;<br/>Netdata plugin: [charts.d.plugin](../collectors/charts.d.plugin#chartsdplugin)<br/>plugin module: [mem_apps.chart.sh](../collectors/charts.d.plugin/mem_apps)<br/>configuration file: [charts.d/mem_apps.conf](../collectors/charts.d.plugin/mem_apps)|
docs/generator/buildyaml.sh
+1
@@ -229,6 +229,7 @@ navpart 3 collectors/ioping.plugin
229 navpart 3 collectors/freeipmi.plugin
230 navpart 3 collectors/nfacct.plugin
231 navpart 3 collectors/xenstat.plugin
232 +navpart 3 collectors/perf.plugin
233
234
235 echo -ne " - 'docs/Third-Party-Plugins.md'
netdata-installer.sh
+19 -14
@@ -55,7 +55,7 @@ download_go() {
55 else
56 echo >&2
57 echo >&2 "Downloading go.d plugin from '${url}' failed because of missing mandatory packages."
58 - echo >&2 "Either add packages or disable it by issuing '--disable-go' in the installer"
58 + echo >&2 "Either add packages or disable it by issuing '--disable-go' in the installer"
59 echo >&2
60
61 run_failed "I need curl or wget to proceed, but neither is available on this system."
@@ -213,10 +213,10 @@ while [ -n "${1}" ]; do
213 "--disable-plugin-nfacct") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-plugin-nfacct/} --disable-plugin-nfacct";;
214 "--enable-plugin-xenstat") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--enable-plugin-xenstat/} --enable-plugin-xenstat";;
215 "--disable-plugin-xenstat") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-plugin-xenstat/} --disable-plugin-xenstat";;
216 - "--enable-backend-kinesis") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--enable-backend-kinesis/} --enable-backend-kinesis";;
217 - "--disable-backend-kinesis") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-backend-kinesis/} --disable-backend-kinesis";;
218 - "--enable-backend-prometheus-remote-write") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--enable-backend-prometheus-remote-write/} --enable-backend-prometheus-remote-write";;
219 - "--disable-backend-prometheus-remote-write") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-backend-prometheus-remote-write/} --disable-backend-prometheus-remote-write";;
216 + "--enable-backend-kinesis") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--enable-backend-kinesis/} --enable-backend-kinesis";;
217 + "--disable-backend-kinesis") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-backend-kinesis/} --disable-backend-kinesis";;
218 + "--enable-backend-prometheus-remote-write") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--enable-backend-prometheus-remote-write/} --enable-backend-prometheus-remote-write";;
219 + "--disable-backend-prometheus-remote-write") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-backend-prometheus-remote-write/} --disable-backend-prometheus-remote-write";;
220 "--enable-lto") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--enable-lto/} --enable-lto";;
221 "--disable-lto") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-lto/} --disable-lto";;
222 "--disable-x86-sse") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-x86-sse/} --disable-x86-sse";;
@@ -736,15 +736,20 @@ if [ "${UID}" -eq 0 ]; then
736 run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/nfacct.plugin"
737 fi
738
739 - if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/xenstat.plugin" ]; then
740 - run chown root:${NETDATA_GROUP} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/xenstat.plugin"
741 - run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/xenstat.plugin"
742 - fi
739 + if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/xenstat.plugin" ]; then
740 + run chown root:${NETDATA_GROUP} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/xenstat.plugin"
741 + run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/xenstat.plugin"
742 + fi
743 +
744 + if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/perf.plugin" ]; then
745 + run chown root:${NETDATA_GROUP} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/perf.plugin"
746 + run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/perf.plugin"
747 + fi
748
744 - if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping" ]; then
745 - run chown root:${NETDATA_GROUP} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping"
746 - run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping"
747 - fi
749 + if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping" ]; then
750 + run chown root:${NETDATA_GROUP} "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping"
751 + run chmod 4750 "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/ioping"
752 + fi
753
754 if [ -f "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/cgroup-network" ]; then
755 run chown "root:${NETDATA_GROUP}" "${NETDATA_PREFIX}/usr/libexec/netdata/plugins.d/cgroup-network"
@@ -876,7 +881,7 @@ else
881 create_netdata_conf "${NETDATA_PREFIX}/etc/netdata/netdata.conf" "http://localhost:${NETDATA_PORT}/netdata.conf"
882 fi
883 if [ "${UID}" -eq 0 ]; then
879 - run chown "${NETDATA_USER}" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
884 + run chown "${NETDATA_USER}" "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
885 fi
886 run chmod 0664 "${NETDATA_PREFIX}/etc/netdata/netdata.conf"
887
web/gui/dashboard_info.js
+6
@@ -473,6 +473,12 @@ netdataDashboard.menu = {
473 title: 'wmi',
474 icon: '<i class="fas fa-server"></i>',
475 info: undefined
476 + },
477 +
478 + 'perf': {
479 + title: 'Perf Counters',
480 + icon: '<i class="fas fa-tachometer-alt"></i>',
481 + info: 'Performance Monitoring Counters (PMC). Data collected using <b>perf_event_open()</b> system call which utilises Hardware Performance Monitoring Units (PMU).'
482 }
483 };
484