updated tests for the new hierarchy (#4464)
Costa Tsaousis committed
Oct 24, 2018 at 00:35 UTC
0a78758a111c10115de56b94dd152bf4cb505cec
8 files changed
+693
-685
.gitignore
+2
@@ -101,6 +101,7 @@ netdata-updater.sh
101
102
# cmake files
103
cmake-build-debug/
104
+cmake-build-release/
105
CMakeCache.txt
106
CMakeFiles/
107
cmake_install.cmake
@@ -130,6 +131,7 @@ tests/profile/benchmark-registry
131
tests/profile/test-eval
132
tests/profile/benchmark-line-parsing
133
tests/profile/benchmark-procfile-parser
134
+tests/profile/benchmark-value-pairs
135
tests/profile/statsd-stress
136
oprofile_data/
137
vgcore.*
libnetdata/adaptive_resortable_list/README.md
+16
-12
@@ -70,18 +70,22 @@ to extract the same number of expected metrics:
70
71
test|code|string comparison|number parsing|duration
72
:---:|:---:|:---:|:---:|:---:|
73
-1|if-else-if-else-if|`strcmp()`|`strtoull()`|4698657 usecs
74
-2|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`strtoull()`| 872005 usecs
75
-3|if-else-if-else-if|statement expression `simple_hash()` and `strcmp()`|`strtoull()`|861626 usecs
76
-4|if-continue|inline `simple_hash()` and `strcmp()`|`strtoull()`|871887 usecs
77
-5|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`str2ull()`|606541 usecs
78
-6|ARL|ARL|`strtoull()`|424149 usecs
79
-7|ARL|ARL|`str2ull()`|199324 usecs
80
-
81
-So, compared to unoptimized code (test No 1: 4.7sec), before ARL netdata was using test
82
-No **5** with hashing and a custom `str2ull()` to achieve 607ms.
83
-The current ARL implementation is test No **7** that needs only 199ms
84
-(23 times faster vs unoptimized code, 3 times faster vs optimized code).
73
+1|if-else-if-else-if|`strcmp()`|`strtoull()`|4630.337 ms
74
+2|nested loops|inline `simple_hash()` and `strcmp()`|`strtoull()`|1597.481 ms
75
+3|nested loops|inline `simple_hash()` and `strcmp()`|`str2ull()`|923.523 ms
76
+4|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`strtoull()`| 854.574 ms
77
+5|if-else-if-else-if|statement expression `simple_hash()` and `strcmp()`|`strtoull()`|912.013 ms
78
+6|if-continue|inline `simple_hash()` and `strcmp()`|`strtoull()`|842.279 ms
79
+7|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`str2ull()`|602.837 ms
80
+8|ARL|ARL|`strtoull()`|350.360 ms
81
+9|ARL|ARL|`str2ull()`|157.237 ms
82
+
83
+Compared to unoptimized code (test No 1: 4.6sec):
84
+
85
+ - before ARL netdata was using test No **7** with hashing and a custom `str2ull()` to achieve 602ms.
86
+ - the current ARL implementation is test No **9** that needs only 157ms (29 times faster vs unoptimized code, about 4 times faster vs optimized code).
87
+
88
+[Check the source code of this test](../../tests/profile/benchmark-value-pairs.c).
89
90
## Limitations
91
tests/profile/Makefile
+46
-5
@@ -1,12 +1,53 @@
1
# SPDX-License-Identifier: GPL-3.0-or-later
2
3
-COMMON_CFLAGS=-I ../../src/ -I ../../
4
-PROFILE_CFLAGS=-O1 -ggdb -Wall -Wextra
3
+COMMON_CFLAGS = -I ../../ -DTARGET_OS=1 -Wall -Wextra
4
+PROFILE_CFLAGS = -O1 -ggdb $(COMMON_CFLAGS)
5
+PERFORMANCE_CFLAGS = -O2 $(COMMON_CFLAGS)
6
+
7
+CFLAGS = $(PERFORMANCE_CFLAGS)
8
+
9
+LIBNETDATA_FILES = \
10
+ ../../libnetdata/popen/popen.o \
11
+ ../../libnetdata/storage_number/storage_number.o \
12
+ ../../libnetdata/avl/avl.o \
13
+ ../../libnetdata/socket/socket.o \
14
+ ../../libnetdata/os.o \
15
+ ../../libnetdata/clocks/clocks.o \
16
+ ../../libnetdata/procfile/procfile.o \
17
+ ../../libnetdata/statistical/statistical.o \
18
+ ../../libnetdata/eval/eval.o \
19
+ ../../libnetdata/threads/threads.o \
20
+ ../../libnetdata/dictionary/dictionary.o \
21
+ ../../libnetdata/simple_pattern/simple_pattern.o \
22
+ ../../libnetdata/url/url.o \
23
+ ../../libnetdata/config/appconfig.o \
24
+ ../../libnetdata/libnetdata.o \
25
+ ../../libnetdata/buffer/buffer.o \
26
+ ../../libnetdata/adaptive_resortable_list/adaptive_resortable_list.o \
27
+ ../../libnetdata/locks/locks.o \
28
+ ../../libnetdata/log/log.o \
29
+ $(NULL)
30
+
31
+COMMON_LDFLAGS = $(LIBNETDATA_FILES) -pthread -lm
32
+
33
+all: statsd-stress benchmark-procfile-parser test-eval benchmark-dictionary benchmark-value-pairs
34
35
benchmark-procfile-parser: benchmark-procfile-parser.c
7
- gcc ${PROFILE_CFLAGS} ${COMMON_CFLAGS} -o $@ $^ ../../src/log.o ../../src/procfile.o ../../src/threads.o ../../src/locks.o ../../src/common.o ../../src/clocks.o ../../src/web_buffer.o ../../src/storage_number.o -pthread -lm
36
+ gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
37
+
38
+benchmark-dictionary: benchmark-dictionary.c
39
+ gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
40
+
41
+benchmark-value-pairs: benchmark-value-pairs.c
42
+ gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
43
44
statsd-stress: statsd-stress.c
10
- gcc -O2 -Wall -Wextra -o $@ $^ -pthread
45
+ gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
46
+
47
+test-eval: test-eval.c
48
+ gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
49
+
50
+
51
+clean:
52
+ rm -f benchmark-procfile-parser statsd-stress test-eval benchmark-dictionary benchmark-value-pairs
53
12
-all: statsd-stress benchmark-procfile-parser
tests/profile/benchmark-dictionary.c
+2
-1
@@ -7,7 +7,8 @@
7
*
8
*/
9
10
-#include "common.h"
10
+#include "config.h"
11
+#include "libnetdata/libnetdata.h"
12
13
struct myvalue {
14
int i;
tests/profile/benchmark-procfile-parser.c
+2
-2
@@ -1,7 +1,7 @@
1
/* SPDX-License-Identifier: GPL-3.0-or-later */
2
+
3
#include "config.h"
3
-#include "common.h"
4
-#include "clocks.h"
4
+#include "libnetdata/libnetdata.h"
5
6
void netdata_cleanup_and_exit(int ret) {
7
exit(ret);
tests/profile/benchmark-strcmp.c
deleted
-663
@@ -1,663 +0,0 @@
1
-/* SPDX-License-Identifier: GPL-3.0-or-later */
2
-#include <stdio.h>
3
-#include <inttypes.h>
4
-#include <string.h>
5
-#include <stdlib.h>
6
-#include <ctype.h>
7
-#include <sys/time.h>
8
-
9
-#define likely(x) __builtin_expect(!!(x), 1)
10
-#define unlikely(x) __builtin_expect(!!(x), 0)
11
-
12
-#define simple_hash(name) ({ \
13
- register unsigned char *__hash_source = (unsigned char *)(name); \
14
- register uint32_t __hash_value = 0x811c9dc5; \
15
- while (*__hash_source) { \
16
- __hash_value *= 16777619; \
17
- __hash_value ^= (uint32_t) *__hash_source++; \
18
- } \
19
- __hash_value; \
20
-})
21
-
22
-static inline uint32_t simple_hash2(const char *name) {
23
- register unsigned char *s = (unsigned char *)name;
24
- register uint32_t hval = 0x811c9dc5;
25
- while (*s) {
26
- hval *= 16777619;
27
- hval ^= (uint32_t) *s++;
28
- }
29
- return hval;
30
-}
31
-
32
-static inline unsigned long long fast_strtoull(const char *s) {
33
- register unsigned long long n = 0;
34
- register char c;
35
- for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
36
- n *= 10;
37
- n += c - '0';
38
- // n = (n << 1) + (n << 3) + (c - '0');
39
- }
40
- return n;
41
-}
42
-
43
-static uint32_t cache_hash = 0;
44
-static uint32_t rss_hash = 0;
45
-static uint32_t rss_huge_hash = 0;
46
-static uint32_t mapped_file_hash = 0;
47
-static uint32_t writeback_hash = 0;
48
-static uint32_t dirty_hash = 0;
49
-static uint32_t swap_hash = 0;
50
-static uint32_t pgpgin_hash = 0;
51
-static uint32_t pgpgout_hash = 0;
52
-static uint32_t pgfault_hash = 0;
53
-static uint32_t pgmajfault_hash = 0;
54
-static uint32_t inactive_anon_hash = 0;
55
-static uint32_t active_anon_hash = 0;
56
-static uint32_t inactive_file_hash = 0;
57
-static uint32_t active_file_hash = 0;
58
-static uint32_t unevictable_hash = 0;
59
-static uint32_t hierarchical_memory_limit_hash = 0;
60
-static uint32_t total_cache_hash = 0;
61
-static uint32_t total_rss_hash = 0;
62
-static uint32_t total_rss_huge_hash = 0;
63
-static uint32_t total_mapped_file_hash = 0;
64
-static uint32_t total_writeback_hash = 0;
65
-static uint32_t total_dirty_hash = 0;
66
-static uint32_t total_swap_hash = 0;
67
-static uint32_t total_pgpgin_hash = 0;
68
-static uint32_t total_pgpgout_hash = 0;
69
-static uint32_t total_pgfault_hash = 0;
70
-static uint32_t total_pgmajfault_hash = 0;
71
-static uint32_t total_inactive_anon_hash = 0;
72
-static uint32_t total_active_anon_hash = 0;
73
-static uint32_t total_inactive_file_hash = 0;
74
-static uint32_t total_active_file_hash = 0;
75
-static uint32_t total_unevictable_hash = 0;
76
-
77
-char *strings[] = {
78
- "cache",
79
- "rss",
80
- "rss_huge",
81
- "mapped_file",
82
- "writeback",
83
- "dirty",
84
- "swap",
85
- "pgpgin",
86
- "pgpgout",
87
- "pgfault",
88
- "pgmajfault",
89
- "inactive_anon",
90
- "active_anon",
91
- "inactive_file",
92
- "active_file",
93
- "unevictable",
94
- "hierarchical_memory_limit",
95
- "total_cache",
96
- "total_rss",
97
- "total_rss_huge",
98
- "total_mapped_file",
99
- "total_writeback",
100
- "total_dirty",
101
- "total_swap",
102
- "total_pgpgin",
103
- "total_pgpgout",
104
- "total_pgfault",
105
- "total_pgmajfault",
106
- "total_inactive_anon",
107
- "total_active_anon",
108
- "total_inactive_file",
109
- "total_active_file",
110
- "total_unevictable",
111
- NULL
112
-};
113
-
114
-unsigned long long values1[12] = { 0 };
115
-unsigned long long values2[12] = { 0 };
116
-unsigned long long values3[12] = { 0 };
117
-unsigned long long values4[12] = { 0 };
118
-unsigned long long values5[12] = { 0 };
119
-unsigned long long values6[12] = { 0 };
120
-
121
-#define NUMBER1 "12345678901234"
122
-#define NUMBER2 "23456789012345"
123
-#define NUMBER3 "34567890123456"
124
-#define NUMBER4 "45678901234567"
125
-#define NUMBER5 "56789012345678"
126
-#define NUMBER6 "67890123456789"
127
-#define NUMBER7 "78901234567890"
128
-#define NUMBER8 "89012345678901"
129
-#define NUMBER9 "90123456789012"
130
-#define NUMBER10 "12345678901234"
131
-#define NUMBER11 "23456789012345"
132
-
133
-// simple system strcmp()
134
-void test1() {
135
- int i;
136
- for(i = 0; strings[i] ; i++) {
137
- char *s = strings[i];
138
-
139
- if(unlikely(!strcmp(s, "cache")))
140
- values1[i] = strtoull(NUMBER1, NULL, 10);
141
-
142
- else if(unlikely(!strcmp(s, "rss")))
143
- values1[i] = strtoull(NUMBER2, NULL, 10);
144
-
145
- else if(unlikely(!strcmp(s, "rss_huge")))
146
- values1[i] = strtoull(NUMBER3, NULL, 10);
147
-
148
- else if(unlikely(!strcmp(s, "mapped_file")))
149
- values1[i] = strtoull(NUMBER4, NULL, 10);
150
-
151
- else if(unlikely(!strcmp(s, "writeback")))
152
- values1[i] = strtoull(NUMBER5, NULL, 10);
153
-
154
- else if(unlikely(!strcmp(s, "dirty")))
155
- values1[i] = strtoull(NUMBER6, NULL, 10);
156
-
157
- else if(unlikely(!strcmp(s, "swap")))
158
- values1[i] = strtoull(NUMBER7, NULL, 10);
159
-
160
- else if(unlikely(!strcmp(s, "pgpgin")))
161
- values1[i] = strtoull(NUMBER8, NULL, 10);
162
-
163
- else if(unlikely(!strcmp(s, "pgpgout")))
164
- values1[i] = strtoull(NUMBER9, NULL, 10);
165
-
166
- else if(unlikely(!strcmp(s, "pgfault")))
167
- values1[i] = strtoull(NUMBER10, NULL, 10);
168
-
169
- else if(unlikely(!strcmp(s, "pgmajfault")))
170
- values1[i] = strtoull(NUMBER11, NULL, 10);
171
- }
172
-}
173
-
174
-// inline simple_hash() with system strtoull()
175
-void test2() {
176
- int i;
177
- for(i = 0; strings[i] ; i++) {
178
- char *s = strings[i];
179
- uint32_t hash = simple_hash2(s);
180
-
181
- if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
182
- values2[i] = strtoull(NUMBER1, NULL, 10);
183
-
184
- else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
185
- values2[i] = strtoull(NUMBER2, NULL, 10);
186
-
187
- else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
188
- values2[i] = strtoull(NUMBER3, NULL, 10);
189
-
190
- else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
191
- values2[i] = strtoull(NUMBER4, NULL, 10);
192
-
193
- else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
194
- values2[i] = strtoull(NUMBER5, NULL, 10);
195
-
196
- else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
197
- values2[i] = strtoull(NUMBER6, NULL, 10);
198
-
199
- else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
200
- values2[i] = strtoull(NUMBER7, NULL, 10);
201
-
202
- else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
203
- values2[i] = strtoull(NUMBER8, NULL, 10);
204
-
205
- else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
206
- values2[i] = strtoull(NUMBER9, NULL, 10);
207
-
208
- else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
209
- values2[i] = strtoull(NUMBER10, NULL, 10);
210
-
211
- else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
212
- values2[i] = strtoull(NUMBER11, NULL, 10);
213
- }
214
-}
215
-
216
-// statement expression simple_hash(), system strtoull()
217
-void test3() {
218
- int i;
219
- for(i = 0; strings[i] ; i++) {
220
- char *s = strings[i];
221
- uint32_t hash = simple_hash(s);
222
-
223
- if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
224
- values3[i] = strtoull(NUMBER1, NULL, 10);
225
-
226
- else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
227
- values3[i] = strtoull(NUMBER2, NULL, 10);
228
-
229
- else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
230
- values3[i] = strtoull(NUMBER3, NULL, 10);
231
-
232
- else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
233
- values3[i] = strtoull(NUMBER4, NULL, 10);
234
-
235
- else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
236
- values3[i] = strtoull(NUMBER5, NULL, 10);
237
-
238
- else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
239
- values3[i] = strtoull(NUMBER6, NULL, 10);
240
-
241
- else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
242
- values3[i] = strtoull(NUMBER7, NULL, 10);
243
-
244
- else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
245
- values3[i] = strtoull(NUMBER8, NULL, 10);
246
-
247
- else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
248
- values3[i] = strtoull(NUMBER9, NULL, 10);
249
-
250
- else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
251
- values3[i] = strtoull(NUMBER10, NULL, 10);
252
-
253
- else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
254
- values3[i] = strtoull(NUMBER11, NULL, 10);
255
- }
256
-}
257
-
258
-
259
-// inline simple_hash(), if-continue checks
260
-void test4() {
261
- int i;
262
- for(i = 0; strings[i] ; i++) {
263
- char *s = strings[i];
264
- uint32_t hash = simple_hash2(s);
265
-
266
- if(unlikely(hash == cache_hash && !strcmp(s, "cache"))) {
267
- values4[i] = strtoull(NUMBER1, NULL, 0);
268
- continue;
269
- }
270
-
271
- if(unlikely(hash == rss_hash && !strcmp(s, "rss"))) {
272
- values4[i] = strtoull(NUMBER2, NULL, 0);
273
- continue;
274
- }
275
-
276
- if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge"))) {
277
- values4[i] = strtoull(NUMBER3, NULL, 0);
278
- continue;
279
- }
280
-
281
- if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file"))) {
282
- values4[i] = strtoull(NUMBER4, NULL, 0);
283
- continue;
284
- }
285
-
286
- if(unlikely(hash == writeback_hash && !strcmp(s, "writeback"))) {
287
- values4[i] = strtoull(NUMBER5, NULL, 0);
288
- continue;
289
- }
290
-
291
- if(unlikely(hash == dirty_hash && !strcmp(s, "dirty"))) {
292
- values4[i] = strtoull(NUMBER6, NULL, 0);
293
- continue;
294
- }
295
-
296
- if(unlikely(hash == swap_hash && !strcmp(s, "swap"))) {
297
- values4[i] = strtoull(NUMBER7, NULL, 0);
298
- continue;
299
- }
300
-
301
- if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin"))) {
302
- values4[i] = strtoull(NUMBER8, NULL, 0);
303
- continue;
304
- }
305
-
306
- if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout"))) {
307
- values4[i] = strtoull(NUMBER9, NULL, 0);
308
- continue;
309
- }
310
-
311
- if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault"))) {
312
- values4[i] = strtoull(NUMBER10, NULL, 0);
313
- continue;
314
- }
315
-
316
- if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))) {
317
- values4[i] = strtoull(NUMBER11, NULL, 0);
318
- continue;
319
- }
320
- }
321
-}
322
-
323
-// inline simple_hash(), if-else-if-else-if (netdata default)
324
-void test5() {
325
- int i;
326
- for(i = 0; strings[i] ; i++) {
327
- char *s = strings[i];
328
- uint32_t hash = simple_hash2(s);
329
-
330
- if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
331
- values5[i] = fast_strtoull(NUMBER1);
332
-
333
- else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
334
- values5[i] = fast_strtoull(NUMBER2);
335
-
336
- else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
337
- values5[i] = fast_strtoull(NUMBER3);
338
-
339
- else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
340
- values5[i] = fast_strtoull(NUMBER4);
341
-
342
- else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
343
- values5[i] = fast_strtoull(NUMBER5);
344
-
345
- else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
346
- values5[i] = fast_strtoull(NUMBER6);
347
-
348
- else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
349
- values5[i] = fast_strtoull(NUMBER7);
350
-
351
- else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
352
- values5[i] = fast_strtoull(NUMBER8);
353
-
354
- else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
355
- values5[i] = fast_strtoull(NUMBER9);
356
-
357
- else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
358
- values5[i] = fast_strtoull(NUMBER10);
359
-
360
- else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
361
- values5[i] = fast_strtoull(NUMBER11);
362
- }
363
-}
364
-
365
-// ----------------------------------------------------------------------------
366
-
367
-struct entry {
368
- char *name;
369
- uint32_t hash;
370
- int found;
371
- void (*func)(void *data1, void *data2);
372
- void *data1;
373
- void *data2;
374
- struct entry *prev, *next;
375
-};
376
-
377
-struct base {
378
- int iteration;
379
- int registered;
380
- int wanted;
381
- int found;
382
- struct entry *entries, *last;
383
-};
384
-
385
-static inline void callback(void *data1, void *data2) {
386
- char *string = data1;
387
- unsigned long long *value = data2;
388
- *value = fast_strtoull(string);
389
-}
390
-
391
-
392
-static inline struct base *entry(struct base *base, const char *name, void *data1, void *data2, void (*func)(void *, void *)) {
393
- if(!base)
394
- base = calloc(1, sizeof(struct base));
395
-
396
- struct entry *e = malloc(sizeof(struct entry));
397
- e->name = strdup(name);
398
- e->hash = simple_hash2(e->name);
399
- e->data1 = data1;
400
- e->data2 = data2;
401
- e->func = func;
402
- e->prev = NULL;
403
- e->next = base->entries;
404
-
405
- if(base->entries) base->entries->prev = e;
406
- else base->last = e;
407
-
408
- base->entries = e;
409
- base->registered++;
410
- base->wanted = base->registered;
411
-
412
- return base;
413
-}
414
-
415
-static inline int check(struct base *base, const char *s) {
416
- uint32_t hash = simple_hash2(s);
417
-
418
- if(likely(hash == base->last->hash && !strcmp(s, base->last->name))) {
419
- base->last->found = 1;
420
- base->found++;
421
- if(base->last->func) base->last->func(base->last->data1, base->last->data2);
422
- base->last = base->last->next;
423
-
424
- if(!base->last)
425
- base->last = base->entries;
426
-
427
- if(base->found == base->registered)
428
- return 1;
429
-
430
- return 0;
431
- }
432
-
433
- // find it
434
- struct entry *e;
435
- for(e = base->entries; e ; e = e->next)
436
- if(e->hash == hash && !strcmp(e->name, s))
437
- break;
438
-
439
- if(e == base->last) {
440
- printf("ERROR\n");
441
- exit(1);
442
- }
443
-
444
- if(e) {
445
- // found
446
-
447
- // run it
448
- if(e->func) e->func(e->data1, e->data2);
449
-
450
- // unlink it
451
- if(e->next) e->next->prev = e->prev;
452
- if(e->prev) e->prev->next = e->next;
453
-
454
- if(base->entries == e)
455
- base->entries = e->next;
456
- }
457
- else {
458
- // not found
459
-
460
- // create it
461
- e = calloc(1, sizeof(struct entry));
462
- e->name = strdup(s);
463
- e->hash = hash;
464
- }
465
-
466
- // link it here
467
- e->next = base->last;
468
- if(base->last) {
469
- e->prev = base->last->prev;
470
- base->last->prev = e;
471
-
472
- if(base->entries == base->last)
473
- base->entries = e;
474
- }
475
- else
476
- e->prev = NULL;
477
-
478
- if(e->prev)
479
- e->prev->next = e;
480
-
481
- base->last = e->next;
482
- if(!base->last)
483
- base->last = base->entries;
484
-
485
- e->found = 1;
486
- base->found++;
487
-
488
- if(base->found == base->registered)
489
- return 1;
490
-
491
- printf("relinked '%s' after '%s' and before '%s': ", e->name, e->prev?e->prev->name:"NONE", e->next?e->next->name:"NONE");
492
- for(e = base->entries; e ; e = e->next) printf("%s ", e->name);
493
- printf("\n");
494
-
495
- return 0;
496
-}
497
-
498
-static inline void begin(struct base *base) {
499
-
500
- if(unlikely(base->iteration % 60) == 1) {
501
- base->wanted = 0;
502
- struct entry *e;
503
- for(e = base->entries; e ; e = e->next)
504
- if(e->found) base->wanted++;
505
- }
506
-
507
- base->iteration++;
508
- base->last = base->entries;
509
- base->found = 0;
510
-}
511
-
512
-void test6() {
513
-
514
- static struct base *base = NULL;
515
-
516
- if(unlikely(!base)) {
517
- base = entry(base, "cache", NUMBER1, &values6[0], callback);
518
- base = entry(base, "rss", NUMBER2, &values6[1], callback);
519
- base = entry(base, "rss_huge", NUMBER3, &values6[2], callback);
520
- base = entry(base, "mapped_file", NUMBER4, &values6[3], callback);
521
- base = entry(base, "writeback", NUMBER5, &values6[4], callback);
522
- base = entry(base, "dirty", NUMBER6, &values6[5], callback);
523
- base = entry(base, "swap", NUMBER7, &values6[6], callback);
524
- base = entry(base, "pgpgin", NUMBER8, &values6[7], callback);
525
- base = entry(base, "pgpgout", NUMBER9, &values6[8], callback);
526
- base = entry(base, "pgfault", NUMBER10, &values6[9], callback);
527
- base = entry(base, "pgmajfault", NUMBER11, &values6[10], callback);
528
- }
529
-
530
- begin(base);
531
-
532
- int i;
533
- for(i = 0; strings[i] ; i++) {
534
- if(check(base, strings[i]))
535
- break;
536
- }
537
-}
538
-
539
-// ----------------------------------------------------------------------------
540
-
541
-
542
-// ==============
543
-// --- Poor man cycle counting.
544
-static unsigned long tsc;
545
-
546
-static void begin_tsc(void)
547
-{
548
- unsigned long a, d;
549
- asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
550
- tsc = ((unsigned long)d << 32) | (unsigned long)a;
551
-}
552
-
553
-static unsigned long end_tsc(void)
554
-{
555
- unsigned long a, d;
556
- asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
557
- return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
558
-}
559
-// ===============
560
-
561
-static unsigned long long clk;
562
-
563
-static void begin_clock() {
564
- struct timeval tv;
565
- if(unlikely(gettimeofday(&tv, NULL) == -1))
566
- return;
567
- clk = tv.tv_sec * 1000000 + tv.tv_usec;
568
-}
569
-
570
-static unsigned long long end_clock() {
571
- struct timeval tv;
572
- if(unlikely(gettimeofday(&tv, NULL) == -1))
573
- return -1;
574
- return clk = tv.tv_sec * 1000000 + tv.tv_usec - clk;
575
-}
576
-
577
-void main(void)
578
-{
579
- cache_hash = simple_hash("cache");
580
- rss_hash = simple_hash("rss");
581
- rss_huge_hash = simple_hash("rss_huge");
582
- mapped_file_hash = simple_hash("mapped_file");
583
- writeback_hash = simple_hash("writeback");
584
- dirty_hash = simple_hash("dirty");
585
- swap_hash = simple_hash("swap");
586
- pgpgin_hash = simple_hash("pgpgin");
587
- pgpgout_hash = simple_hash("pgpgout");
588
- pgfault_hash = simple_hash("pgfault");
589
- pgmajfault_hash = simple_hash("pgmajfault");
590
- inactive_anon_hash = simple_hash("inactive_anon");
591
- active_anon_hash = simple_hash("active_anon");
592
- inactive_file_hash = simple_hash("inactive_file");
593
- active_file_hash = simple_hash("active_file");
594
- unevictable_hash = simple_hash("unevictable");
595
- hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
596
- total_cache_hash = simple_hash("total_cache");
597
- total_rss_hash = simple_hash("total_rss");
598
- total_rss_huge_hash = simple_hash("total_rss_huge");
599
- total_mapped_file_hash = simple_hash("total_mapped_file");
600
- total_writeback_hash = simple_hash("total_writeback");
601
- total_dirty_hash = simple_hash("total_dirty");
602
- total_swap_hash = simple_hash("total_swap");
603
- total_pgpgin_hash = simple_hash("total_pgpgin");
604
- total_pgpgout_hash = simple_hash("total_pgpgout");
605
- total_pgfault_hash = simple_hash("total_pgfault");
606
- total_pgmajfault_hash = simple_hash("total_pgmajfault");
607
- total_inactive_anon_hash = simple_hash("total_inactive_anon");
608
- total_active_anon_hash = simple_hash("total_active_anon");
609
- total_inactive_file_hash = simple_hash("total_inactive_file");
610
- total_active_file_hash = simple_hash("total_active_file");
611
- total_unevictable_hash = simple_hash("total_unevictable");
612
-
613
- // cache functions
614
- (void)simple_hash2("hello world");
615
- (void)strcmp("1", "2");
616
- (void)strtoull("123", NULL, 0);
617
-
618
- unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0;
619
- unsigned long max = 200000;
620
-
621
- begin_clock();
622
- for(i = 0; i <= max ;i++) test1();
623
- c1 = end_clock();
624
-
625
- begin_clock();
626
- for(i = 0; i <= max ;i++) test2();
627
- c2 = end_clock();
628
-
629
- begin_clock();
630
- for(i = 0; i <= max ;i++) test3();
631
- c3 = end_clock();
632
-
633
- begin_clock();
634
- for(i = 0; i <= max ;i++) test4();
635
- c4 = end_clock();
636
-
637
- begin_clock();
638
- for(i = 0; i <= max ;i++) test5();
639
- c5 = end_clock();
640
-
641
- begin_clock();
642
- for(i = 0; i <= max ;i++) test6();
643
- c6 = end_clock();
644
-
645
- for(i = 0; i < 11 ; i++)
646
- printf("value %lu: %llu %llu %llu %llu %llu %llu\n", i, values1[i], values2[i], values3[i], values4[i], values5[i], values6[i]);
647
-
648
- printf("\n\nRESULTS\n");
649
- printf("test1() in %lu usecs: simple system strcmp().\n"
650
- "test2() in %lu usecs: inline simple_hash() with system strtoull().\n"
651
- "test3() in %lu usecs: statement expression simple_hash(), system strtoull().\n"
652
- "test4() in %lu usecs: inline simple_hash(), if-continue checks.\n"
653
- "test5() in %lu usecs: inline simple_hash(), if-else-if-else-if (netdata default).\n"
654
- "test6() in %lu usecs: adaptive re-sortable array (wow!)\n"
655
- , c1
656
- , c2
657
- , c3
658
- , c4
659
- , c5
660
- , c6
661
- );
662
-
663
-}
tests/profile/benchmark-value-pairs.c
new
+623
@@ -0,0 +1,623 @@
1
+/* SPDX-License-Identifier: GPL-3.0-or-later */
2
+
3
+#include "config.h"
4
+#include "libnetdata/libnetdata.h"
5
+
6
+#ifdef simple_hash
7
+#undef simple_hash
8
+#endif
9
+
10
+void netdata_cleanup_and_exit(int ret) {
11
+ exit(ret);
12
+}
13
+
14
+#define simple_hash(name) ({ \
15
+ register unsigned char *__hash_source = (unsigned char *)(name); \
16
+ register uint32_t __hash_value = 0x811c9dc5; \
17
+ while (*__hash_source) { \
18
+ __hash_value *= 16777619; \
19
+ __hash_value ^= (uint32_t) *__hash_source++; \
20
+ } \
21
+ __hash_value; \
22
+})
23
+
24
+static inline uint32_t simple_hash2(const char *name) {
25
+ register unsigned char *s = (unsigned char *)name;
26
+ register uint32_t hval = 0x811c9dc5;
27
+ while (*s) {
28
+ hval *= 16777619;
29
+ hval ^= (uint32_t) *s++;
30
+ }
31
+ return hval;
32
+}
33
+
34
+static inline unsigned long long fast_strtoull(const char *s) {
35
+ register unsigned long long n = 0;
36
+ register char c;
37
+ for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
38
+ n *= 10;
39
+ n += c - '0';
40
+ // n = (n << 1) + (n << 3) + (c - '0');
41
+ }
42
+ return n;
43
+}
44
+
45
+static uint32_t cache_hash = 0;
46
+static uint32_t rss_hash = 0;
47
+static uint32_t rss_huge_hash = 0;
48
+static uint32_t mapped_file_hash = 0;
49
+static uint32_t writeback_hash = 0;
50
+static uint32_t dirty_hash = 0;
51
+static uint32_t swap_hash = 0;
52
+static uint32_t pgpgin_hash = 0;
53
+static uint32_t pgpgout_hash = 0;
54
+static uint32_t pgfault_hash = 0;
55
+static uint32_t pgmajfault_hash = 0;
56
+static uint32_t inactive_anon_hash = 0;
57
+static uint32_t active_anon_hash = 0;
58
+static uint32_t inactive_file_hash = 0;
59
+static uint32_t active_file_hash = 0;
60
+static uint32_t unevictable_hash = 0;
61
+static uint32_t hierarchical_memory_limit_hash = 0;
62
+static uint32_t total_cache_hash = 0;
63
+static uint32_t total_rss_hash = 0;
64
+static uint32_t total_rss_huge_hash = 0;
65
+static uint32_t total_mapped_file_hash = 0;
66
+static uint32_t total_writeback_hash = 0;
67
+static uint32_t total_dirty_hash = 0;
68
+static uint32_t total_swap_hash = 0;
69
+static uint32_t total_pgpgin_hash = 0;
70
+static uint32_t total_pgpgout_hash = 0;
71
+static uint32_t total_pgfault_hash = 0;
72
+static uint32_t total_pgmajfault_hash = 0;
73
+static uint32_t total_inactive_anon_hash = 0;
74
+static uint32_t total_active_anon_hash = 0;
75
+static uint32_t total_inactive_file_hash = 0;
76
+static uint32_t total_active_file_hash = 0;
77
+static uint32_t total_unevictable_hash = 0;
78
+
79
+unsigned long long values1[50] = { 0 };
80
+unsigned long long values2[50] = { 0 };
81
+unsigned long long values3[50] = { 0 };
82
+unsigned long long values4[50] = { 0 };
83
+unsigned long long values5[50] = { 0 };
84
+unsigned long long values6[50] = { 0 };
85
+unsigned long long values7[50] = { 0 };
86
+unsigned long long values8[50] = { 0 };
87
+unsigned long long values9[50] = { 0 };
88
+
89
+struct pair {
90
+ const char *name;
91
+ const char *value;
92
+ uint32_t hash;
93
+ unsigned long long *collected8;
94
+ unsigned long long *collected9;
95
+} pairs[] = {
96
+ { "cache", "12345678901234", 0, &values8[0] ,&values9[0] },
97
+ { "rss", "23456789012345", 0, &values8[1] ,&values9[1] },
98
+ { "rss_huge", "34567890123456", 0, &values8[2] ,&values9[2] },
99
+ { "mapped_file", "45678901234567", 0, &values8[3] ,&values9[3] },
100
+ { "writeback", "56789012345678", 0, &values8[4] ,&values9[4] },
101
+ { "dirty", "67890123456789", 0, &values8[5] ,&values9[5] },
102
+ { "swap", "78901234567890", 0, &values8[6] ,&values9[6] },
103
+ { "pgpgin", "89012345678901", 0, &values8[7] ,&values9[7] },
104
+ { "pgpgout", "90123456789012", 0, &values8[8] ,&values9[8] },
105
+ { "pgfault", "10345678901234", 0, &values8[9] ,&values9[9] },
106
+ { "pgmajfault", "11456789012345", 0, &values8[10] ,&values9[10] },
107
+ { "inactive_anon", "12000000000000", 0, &values8[11] ,&values9[11] },
108
+ { "active_anon", "13345678901234", 0, &values8[12] ,&values9[12] },
109
+ { "inactive_file", "14345678901234", 0, &values8[13] ,&values9[13] },
110
+ { "active_file", "15345678901234", 0, &values8[14] ,&values9[14] },
111
+ { "unevictable", "16345678901234", 0, &values8[15] ,&values9[15] },
112
+ { "hierarchical_memory_limit", "17345678901234", 0, &values8[16] ,&values9[16] },
113
+ { "total_cache", "18345678901234", 0, &values8[17] ,&values9[17] },
114
+ { "total_rss", "19345678901234", 0, &values8[18] ,&values9[18] },
115
+ { "total_rss_huge", "20345678901234", 0, &values8[19] ,&values9[19] },
116
+ { "total_mapped_file", "21345678901234", 0, &values8[20] ,&values9[20] },
117
+ { "total_writeback", "22345678901234", 0, &values8[21] ,&values9[21] },
118
+ { "total_dirty", "23000000000000", 0, &values8[22] ,&values9[22] },
119
+ { "total_swap", "24345678901234", 0, &values8[23] ,&values9[23] },
120
+ { "total_pgpgin", "25345678901234", 0, &values8[24] ,&values9[24] },
121
+ { "total_pgpgout", "26345678901234", 0, &values8[25] ,&values9[25] },
122
+ { "total_pgfault", "27345678901234", 0, &values8[26] ,&values9[26] },
123
+ { "total_pgmajfault", "28345678901234", 0, &values8[27] ,&values9[27] },
124
+ { "total_inactive_anon", "29345678901234", 0, &values8[28] ,&values9[28] },
125
+ { "total_active_anon", "30345678901234", 0, &values8[29] ,&values9[29] },
126
+ { "total_inactive_file", "31345678901234", 0, &values8[30] ,&values9[30] },
127
+ { "total_active_file", "32345678901234", 0, &values8[31] ,&values9[31] },
128
+ { "total_unevictable", "33345678901234", 0, &values8[32] ,&values9[32] },
129
+ { NULL, NULL , 0, NULL ,NULL }
130
+};
131
+
132
+// simple system strcmp()
133
+void test1() {
134
+ int i;
135
+ for(i = 0; pairs[i].name ; i++) {
136
+ const char *s = pairs[i].name;
137
+ const char *v = pairs[i].value;
138
+
139
+ if(unlikely(!strcmp(s, "cache")))
140
+ values1[i] = strtoull(v, NULL, 10);
141
+
142
+ else if(unlikely(!strcmp(s, "rss")))
143
+ values1[i] = strtoull(v, NULL, 10);
144
+
145
+ else if(unlikely(!strcmp(s, "rss_huge")))
146
+ values1[i] = strtoull(v, NULL, 10);
147
+
148
+ else if(unlikely(!strcmp(s, "mapped_file")))
149
+ values1[i] = strtoull(v, NULL, 10);
150
+
151
+ else if(unlikely(!strcmp(s, "writeback")))
152
+ values1[i] = strtoull(v, NULL, 10);
153
+
154
+ else if(unlikely(!strcmp(s, "dirty")))
155
+ values1[i] = strtoull(v, NULL, 10);
156
+
157
+ else if(unlikely(!strcmp(s, "swap")))
158
+ values1[i] = strtoull(v, NULL, 10);
159
+
160
+ else if(unlikely(!strcmp(s, "pgpgin")))
161
+ values1[i] = strtoull(v, NULL, 10);
162
+
163
+ else if(unlikely(!strcmp(s, "pgpgout")))
164
+ values1[i] = strtoull(v, NULL, 10);
165
+
166
+ else if(unlikely(!strcmp(s, "pgfault")))
167
+ values1[i] = strtoull(v, NULL, 10);
168
+
169
+ else if(unlikely(!strcmp(s, "pgmajfault")))
170
+ values1[i] = strtoull(v, NULL, 10);
171
+ }
172
+}
173
+
174
+// inline simple_hash() with system strtoull()
175
+void test2() {
176
+ int i;
177
+ for(i = 0; pairs[i].name ; i++) {
178
+ const char *s = pairs[i].name;
179
+ const char *v = pairs[i].value;
180
+
181
+ uint32_t hash = simple_hash2(s);
182
+
183
+ if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
184
+ values2[i] = strtoull(v, NULL, 10);
185
+
186
+ else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
187
+ values2[i] = strtoull(v, NULL, 10);
188
+
189
+ else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
190
+ values2[i] = strtoull(v, NULL, 10);
191
+
192
+ else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
193
+ values2[i] = strtoull(v, NULL, 10);
194
+
195
+ else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
196
+ values2[i] = strtoull(v, NULL, 10);
197
+
198
+ else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
199
+ values2[i] = strtoull(v, NULL, 10);
200
+
201
+ else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
202
+ values2[i] = strtoull(v, NULL, 10);
203
+
204
+ else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
205
+ values2[i] = strtoull(v, NULL, 10);
206
+
207
+ else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
208
+ values2[i] = strtoull(v, NULL, 10);
209
+
210
+ else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
211
+ values2[i] = strtoull(v, NULL, 10);
212
+
213
+ else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
214
+ values2[i] = strtoull(v, NULL, 10);
215
+ }
216
+}
217
+
218
+// statement expression simple_hash(), system strtoull()
219
+void test3() {
220
+ int i;
221
+ for(i = 0; pairs[i].name ; i++) {
222
+ const char *s = pairs[i].name;
223
+ const char *v = pairs[i].value;
224
+
225
+ uint32_t hash = simple_hash(s);
226
+
227
+ if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
228
+ values3[i] = strtoull(v, NULL, 10);
229
+
230
+ else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
231
+ values3[i] = strtoull(v, NULL, 10);
232
+
233
+ else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
234
+ values3[i] = strtoull(v, NULL, 10);
235
+
236
+ else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
237
+ values3[i] = strtoull(v, NULL, 10);
238
+
239
+ else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
240
+ values3[i] = strtoull(v, NULL, 10);
241
+
242
+ else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
243
+ values3[i] = strtoull(v, NULL, 10);
244
+
245
+ else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
246
+ values3[i] = strtoull(v, NULL, 10);
247
+
248
+ else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
249
+ values3[i] = strtoull(v, NULL, 10);
250
+
251
+ else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
252
+ values3[i] = strtoull(v, NULL, 10);
253
+
254
+ else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
255
+ values3[i] = strtoull(v, NULL, 10);
256
+
257
+ else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
258
+ values3[i] = strtoull(v, NULL, 10);
259
+ }
260
+}
261
+
262
+
263
+// inline simple_hash(), if-continue checks
264
+void test4() {
265
+ int i;
266
+ for(i = 0; pairs[i].name ; i++) {
267
+ const char *s = pairs[i].name;
268
+ const char *v = pairs[i].value;
269
+
270
+ uint32_t hash = simple_hash2(s);
271
+
272
+ if(unlikely(hash == cache_hash && !strcmp(s, "cache"))) {
273
+ values4[i] = strtoull(v, NULL, 0);
274
+ continue;
275
+ }
276
+
277
+ if(unlikely(hash == rss_hash && !strcmp(s, "rss"))) {
278
+ values4[i] = strtoull(v, NULL, 0);
279
+ continue;
280
+ }
281
+
282
+ if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge"))) {
283
+ values4[i] = strtoull(v, NULL, 0);
284
+ continue;
285
+ }
286
+
287
+ if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file"))) {
288
+ values4[i] = strtoull(v, NULL, 0);
289
+ continue;
290
+ }
291
+
292
+ if(unlikely(hash == writeback_hash && !strcmp(s, "writeback"))) {
293
+ values4[i] = strtoull(v, NULL, 0);
294
+ continue;
295
+ }
296
+
297
+ if(unlikely(hash == dirty_hash && !strcmp(s, "dirty"))) {
298
+ values4[i] = strtoull(v, NULL, 0);
299
+ continue;
300
+ }
301
+
302
+ if(unlikely(hash == swap_hash && !strcmp(s, "swap"))) {
303
+ values4[i] = strtoull(v, NULL, 0);
304
+ continue;
305
+ }
306
+
307
+ if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin"))) {
308
+ values4[i] = strtoull(v, NULL, 0);
309
+ continue;
310
+ }
311
+
312
+ if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout"))) {
313
+ values4[i] = strtoull(v, NULL, 0);
314
+ continue;
315
+ }
316
+
317
+ if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault"))) {
318
+ values4[i] = strtoull(v, NULL, 0);
319
+ continue;
320
+ }
321
+
322
+ if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))) {
323
+ values4[i] = strtoull(v, NULL, 0);
324
+ continue;
325
+ }
326
+ }
327
+}
328
+
329
+// inline simple_hash(), if-else-if-else-if (netdata default)
330
+void test5() {
331
+ int i;
332
+ for(i = 0; pairs[i].name ; i++) {
333
+ const char *s = pairs[i].name;
334
+ const char *v = pairs[i].value;
335
+
336
+ uint32_t hash = simple_hash2(s);
337
+
338
+ if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
339
+ values5[i] = fast_strtoull(v);
340
+
341
+ else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
342
+ values5[i] = fast_strtoull(v);
343
+
344
+ else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
345
+ values5[i] = fast_strtoull(v);
346
+
347
+ else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
348
+ values5[i] = fast_strtoull(v);
349
+
350
+ else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
351
+ values5[i] = fast_strtoull(v);
352
+
353
+ else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
354
+ values5[i] = fast_strtoull(v);
355
+
356
+ else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
357
+ values5[i] = fast_strtoull(v);
358
+
359
+ else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
360
+ values5[i] = fast_strtoull(v);
361
+
362
+ else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
363
+ values5[i] = fast_strtoull(v);
364
+
365
+ else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
366
+ values5[i] = fast_strtoull(v);
367
+
368
+ else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
369
+ values5[i] = fast_strtoull(v);
370
+ }
371
+}
372
+
373
+// ----------------------------------------------------------------------------
374
+
375
+void arl_strtoull(const char *name, uint32_t hash, const char *value, void *dst) {
376
+ (void)name;
377
+ (void)hash;
378
+
379
+ register unsigned long long *d = dst;
380
+ *d = strtoull(value, NULL, 10);
381
+ // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, *d);
382
+}
383
+
384
+void test6() {
385
+ static ARL_BASE *base = NULL;
386
+
387
+ if(unlikely(!base)) {
388
+ base = arl_create("test6", arl_strtoull, 60);
389
+ arl_expect_custom(base, "cache", NULL, &values6[0]);
390
+ arl_expect_custom(base, "rss", NULL, &values6[1]);
391
+ arl_expect_custom(base, "rss_huge", NULL, &values6[2]);
392
+ arl_expect_custom(base, "mapped_file", NULL, &values6[3]);
393
+ arl_expect_custom(base, "writeback", NULL, &values6[4]);
394
+ arl_expect_custom(base, "dirty", NULL, &values6[5]);
395
+ arl_expect_custom(base, "swap", NULL, &values6[6]);
396
+ arl_expect_custom(base, "pgpgin", NULL, &values6[7]);
397
+ arl_expect_custom(base, "pgpgout", NULL, &values6[8]);
398
+ arl_expect_custom(base, "pgfault", NULL, &values6[9]);
399
+ arl_expect_custom(base, "pgmajfault", NULL, &values6[10]);
400
+ }
401
+
402
+ arl_begin(base);
403
+
404
+ int i;
405
+ for(i = 0; pairs[i].name ; i++)
406
+ if(arl_check(base, pairs[i].name, pairs[i].value)) break;
407
+}
408
+
409
+void arl_str2ull(const char *name, uint32_t hash, const char *value, void *dst) {
410
+ (void)name;
411
+ (void)hash;
412
+
413
+ register unsigned long long *d = dst;
414
+ *d = str2ull(value);
415
+ // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, *d);
416
+}
417
+
418
+void test7() {
419
+ static ARL_BASE *base = NULL;
420
+
421
+ if(unlikely(!base)) {
422
+ base = arl_create("test7", arl_str2ull, 60);
423
+ arl_expect_custom(base, "cache", NULL, &values7[0]);
424
+ arl_expect_custom(base, "rss", NULL, &values7[1]);
425
+ arl_expect_custom(base, "rss_huge", NULL, &values7[2]);
426
+ arl_expect_custom(base, "mapped_file", NULL, &values7[3]);
427
+ arl_expect_custom(base, "writeback", NULL, &values7[4]);
428
+ arl_expect_custom(base, "dirty", NULL, &values7[5]);
429
+ arl_expect_custom(base, "swap", NULL, &values7[6]);
430
+ arl_expect_custom(base, "pgpgin", NULL, &values7[7]);
431
+ arl_expect_custom(base, "pgpgout", NULL, &values7[8]);
432
+ arl_expect_custom(base, "pgfault", NULL, &values7[9]);
433
+ arl_expect_custom(base, "pgmajfault", NULL, &values7[10]);
434
+ }
435
+
436
+ arl_begin(base);
437
+
438
+ int i;
439
+ for(i = 0; pairs[i].name ; i++)
440
+ if(arl_check(base, pairs[i].name, pairs[i].value)) break;
441
+}
442
+
443
+void test8() {
444
+ int i;
445
+ for(i = 0; pairs[i].name; i++) {
446
+ uint32_t hash = simple_hash(pairs[i].name);
447
+
448
+ int j;
449
+ for(j = 0; pairs[j].name; j++) {
450
+ if(hash == pairs[j].hash && !strcmp(pairs[i].name, pairs[j].name)) {
451
+ *pairs[j].collected8 = strtoull(pairs[i].value, NULL, 10);
452
+ break;
453
+ }
454
+ }
455
+ }
456
+}
457
+
458
+void test9() {
459
+ int i;
460
+ for(i = 0; pairs[i].name; i++) {
461
+ uint32_t hash = simple_hash(pairs[i].name);
462
+
463
+ int j;
464
+ for(j = 0; pairs[j].name; j++) {
465
+ if(hash == pairs[j].hash && !strcmp(pairs[i].name, pairs[j].name)) {
466
+ *pairs[j].collected9 = str2ull(pairs[i].value);
467
+ break;
468
+ }
469
+ }
470
+ }
471
+}
472
+
473
+// ----------------------------------------------------------------------------
474
+
475
+/*
476
+// ==============
477
+// --- Poor man cycle counting.
478
+static unsigned long tsc;
479
+
480
+static void begin_tsc(void)
481
+{
482
+ unsigned long a, d;
483
+ asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
484
+ tsc = ((unsigned long)d << 32) | (unsigned long)a;
485
+}
486
+
487
+static unsigned long end_tsc(void)
488
+{
489
+ unsigned long a, d;
490
+ asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
491
+ return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
492
+}
493
+// ===============
494
+*/
495
+
496
+static unsigned long long clk;
497
+
498
+static void begin_clock() {
499
+ struct timeval tv;
500
+ if(unlikely(gettimeofday(&tv, NULL) == -1))
501
+ return;
502
+ clk = tv.tv_sec * 1000000 + tv.tv_usec;
503
+}
504
+
505
+static unsigned long long end_clock() {
506
+ struct timeval tv;
507
+ if(unlikely(gettimeofday(&tv, NULL) == -1))
508
+ return -1;
509
+ return clk = tv.tv_sec * 1000000 + tv.tv_usec - clk;
510
+}
511
+
512
+int main(void)
513
+{
514
+ {
515
+ int i;
516
+ for(i = 0; pairs[i].name; i++)
517
+ pairs[i].hash = simple_hash(pairs[i].name);
518
+ }
519
+
520
+ cache_hash = simple_hash("cache");
521
+ rss_hash = simple_hash("rss");
522
+ rss_huge_hash = simple_hash("rss_huge");
523
+ mapped_file_hash = simple_hash("mapped_file");
524
+ writeback_hash = simple_hash("writeback");
525
+ dirty_hash = simple_hash("dirty");
526
+ swap_hash = simple_hash("swap");
527
+ pgpgin_hash = simple_hash("pgpgin");
528
+ pgpgout_hash = simple_hash("pgpgout");
529
+ pgfault_hash = simple_hash("pgfault");
530
+ pgmajfault_hash = simple_hash("pgmajfault");
531
+ inactive_anon_hash = simple_hash("inactive_anon");
532
+ active_anon_hash = simple_hash("active_anon");
533
+ inactive_file_hash = simple_hash("inactive_file");
534
+ active_file_hash = simple_hash("active_file");
535
+ unevictable_hash = simple_hash("unevictable");
536
+ hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
537
+ total_cache_hash = simple_hash("total_cache");
538
+ total_rss_hash = simple_hash("total_rss");
539
+ total_rss_huge_hash = simple_hash("total_rss_huge");
540
+ total_mapped_file_hash = simple_hash("total_mapped_file");
541
+ total_writeback_hash = simple_hash("total_writeback");
542
+ total_dirty_hash = simple_hash("total_dirty");
543
+ total_swap_hash = simple_hash("total_swap");
544
+ total_pgpgin_hash = simple_hash("total_pgpgin");
545
+ total_pgpgout_hash = simple_hash("total_pgpgout");
546
+ total_pgfault_hash = simple_hash("total_pgfault");
547
+ total_pgmajfault_hash = simple_hash("total_pgmajfault");
548
+ total_inactive_anon_hash = simple_hash("total_inactive_anon");
549
+ total_active_anon_hash = simple_hash("total_active_anon");
550
+ total_inactive_file_hash = simple_hash("total_inactive_file");
551
+ total_active_file_hash = simple_hash("total_active_file");
552
+ total_unevictable_hash = simple_hash("total_unevictable");
553
+
554
+ // cache functions
555
+ (void)simple_hash2("hello world");
556
+ (void)strcmp("1", "2");
557
+ (void)strtoull("123", NULL, 0);
558
+
559
+ unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0, c7 = 0, c8 = 0, c9 = 0;
560
+ unsigned long max = 1000000;
561
+
562
+ begin_clock();
563
+ for(i = 0; i <= max ;i++) test1();
564
+ c1 = end_clock();
565
+
566
+ begin_clock();
567
+ for(i = 0; i <= max ;i++) test2();
568
+ c2 = end_clock();
569
+
570
+ begin_clock();
571
+ for(i = 0; i <= max ;i++) test3();
572
+ c3 = end_clock();
573
+
574
+ begin_clock();
575
+ for(i = 0; i <= max ;i++) test4();
576
+ c4 = end_clock();
577
+
578
+ begin_clock();
579
+ for(i = 0; i <= max ;i++) test5();
580
+ c5 = end_clock();
581
+
582
+ begin_clock();
583
+ for(i = 0; i <= max ;i++) test6();
584
+ c6 = end_clock();
585
+
586
+ begin_clock();
587
+ for(i = 0; i <= max ;i++) test7();
588
+ c7 = end_clock();
589
+
590
+ begin_clock();
591
+ for(i = 0; i <= max ;i++) test8();
592
+ c8 = end_clock();
593
+
594
+ begin_clock();
595
+ for(i = 0; i <= max ;i++) test9();
596
+ c9 = end_clock();
597
+
598
+ for(i = 0; i < 11 ; i++)
599
+ printf("value %lu: %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", i, values1[i], values2[i], values3[i], values4[i], values5[i], values6[i], values7[i], values8[i], values9[i]);
600
+
601
+ printf("\n\nRESULTS\n");
602
+ printf("test1() [1] in %lu usecs: simple system strcmp().\n"
603
+ "test2() [4] in %lu usecs: inline simple_hash() with system strtoull().\n"
604
+ "test3() [5] in %lu usecs: statement expression simple_hash(), system strtoull().\n"
605
+ "test4() [6] in %lu usecs: inline simple_hash(), if-continue checks.\n"
606
+ "test5() [7] in %lu usecs: inline simple_hash(), if-else-if-else-if (netdata default prior to ARL).\n"
607
+ "test6() [8] in %lu usecs: adaptive re-sortable array with strtoull() (wow!)\n"
608
+ "test7() [9] in %lu usecs: adaptive re-sortable array with str2ull() (wow!)\n"
609
+ "test8() [2] in %lu usecs: nested loop with strtoull()\n"
610
+ "test9() [3] in %lu usecs: nested loop with str2ull()\n"
611
+ , c1
612
+ , c2
613
+ , c3
614
+ , c4
615
+ , c5
616
+ , c6
617
+ , c7
618
+ , c8
619
+ , c9
620
+ );
621
+
622
+ return 0;
623
+}
tests/profile/test-eval.c
+2
-2
@@ -8,8 +8,8 @@
8
*/
9
10
#include "config.h"
11
-#include "common.h"
12
-#include "clocks.h"
11
+#include "libnetdata/libnetdata.h"
12
+#include "database/rrdcalc.h"
13
14
void netdata_cleanup_and_exit(int ret) { exit(ret); }
15