@cryptotaxi247 / netdata-1 / commits / 0a78758a1

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