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
+[]()
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/> <br/>[Documentation of `apps.plugin`](../collectors/apps.plugin/).<br/> <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/> <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/> <br/>[Documentation of `perf.plugin`](../collectors/perf.plugin/).<br/> <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/> <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/> <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/> <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