@cryptotaxi247 / netdata-1 / commits / 4c5afdd51

gitignore cleanup and benchmark tests added

Costa Tsaousis (ktsaou) committed Feb 19, 2018 at 21:35 UTC 4c5afdd516692c55fea048e38e58a634532a1e04
5 files changed +1698 -40
.gitignore
+39 -39
@@ -5,6 +5,9 @@
5 config.h.in
6 Makefile.in
7 *~
8 +*.old
9 +*.log
10 +*.pyc
11
12 Makefile
13 aclocal.m4
@@ -12,7 +15,6 @@ autom4te.cache
15 compile
16 config.guess
17 config.h
15 -config.log
18 config.status
19 config.sub
20 configure
@@ -22,45 +24,37 @@ libtool
24 ltmain.sh
25 missing
26 stamp-h1
27 +netdata.spec
28
29 +# netdata binaries
30 netdata
31 apps.plugin
32 freeipmi.plugin
29 -netdata.spec
33 +cgroup-network
34
35 +# netdata makeself archives
36 *.tar.*
37 +*.run
38
33 -cmake-build-debug/
39 +# netdata makeself downloads
40 makeself/tmp/
35 -sitespeed-result/
41 +
42 +# coverity
43 cov-int/
44 netdata-coverity-analysis.tgz
45 .coverity-token
46 .coverity-build
47
41 -.cproject
48 +.cproject/
49 .idea/
50 .vscode/
44 -.project
51 +.project/
52 +.settings/
53 README
54 TODO.md
47 -asan_symbolize.py
48 -charts.d/bind.chart.sh
55 conf.d/netdata.conf
50 -conf.d/netdata.conf.old
51 -isolate-0x1e0e170-v8.log
52 -lan-hosts.sh
53 -modp_numtoa.c
54 -plugins.d/apache_mod_status.plugin
55 -plugins.d/apps.plugin.old
56 -src/.cproject
57 -src/.project
58 -src/.settings/
56 src/TODO.txt
60 -src/rrddim_file.c
61 -system/netdata.service
62 -valgrind.log
63 -valgrind2.log
57 +
58 web/chart-info/
59 web/control.html
60 web/datasource.css
@@ -76,43 +70,49 @@ system/netdata-lsb
70 system/netdata-openrc
71 system/netdata-init-d
72 system/netdata.logrotate
79 -python.d/python-modules-installer.sh
73 +system/netdata.service
74 +system/netdata-freebsd
75
81 -netdata-installer.log
76 +# installer generated files
77 netdata-uninstaller.sh
78 netdata-updater.sh
79
85 -gmon.out
86 -gmon.txt
87 -apps.plugin-profiler.sh
88 -
80 +# cmake files
81 +cmake-build-debug/
82 CMakeCache.txt
83 CMakeFiles/
84 cmake_install.cmake
85
86 +# jetbrains IDE
87 .jetbrains*
88
89 .DS_Store
90
91 contrib/debian/changelog
98 -profile/benchmark-dictionary
99 -profile/benchmark-registry
100 -profile/test-eval
101 -profile/benchmark-line-parsing
102 -profile/statsd-stress
103 -
104 -*.pyc
105 -*.run
92
93 +# converted diagrams
94 diagrams/*.png
95 diagrams/*.svg
96 diagrams/*.atxt
97 diagrams/plantuml.jar
98
112 -src/cgroup-network
113 -vgcore.*
114 -
99 +# cppcheck
100 src/cppcheck-build/
116 -makeself/debug/
101
102 +# debugging / profiling
103 +makeself/debug/
104 +profile/benchmark-dictionary
105 +profile/benchmark-registry
106 +profile/test-eval
107 +profile/benchmark-line-parsing
108 +profile/benchmark-procfile-parser
109 +profile/statsd-stress
110 +oprofile_data/
111 +vgcore.*
112 +callgrind.out.*
113 +gmon.out
114 +gmon.txt
115 +sitespeed-result/
116
117 +# tests and temp files
118 +python.d/python-modules-installer.sh
profile/Makefile
+7 -1
@@ -1,5 +1,11 @@
1
2 +COMMON_CFLAGS=-I ../src/ -I ../
3 +PROFILE_CFLAGS=-O1 -ggdb -Wall -Wextra
4 +
5 +benchmark-procfile-parser: benchmark-procfile-parser.c
6 + 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
7 +
8 statsd-stress: statsd-stress.c
9 gcc -O2 -Wall -Wextra -o $@ $^ -pthread
10
5 -all: statsd-stress
11 +all: statsd-stress benchmark-procfile-parser
profile/benchmark-line-parsing.c new
+662
@@ -0,0 +1,662 @@
1 +#include <stdio.h>
2 +#include <inttypes.h>
3 +#include <string.h>
4 +#include <stdlib.h>
5 +#include <ctype.h>
6 +#include <sys/time.h>
7 +
8 +#define likely(x) __builtin_expect(!!(x), 1)
9 +#define unlikely(x) __builtin_expect(!!(x), 0)
10 +
11 +#define simple_hash(name) ({ \
12 + register unsigned char *__hash_source = (unsigned char *)(name); \
13 + register uint32_t __hash_value = 0x811c9dc5; \
14 + while (*__hash_source) { \
15 + __hash_value *= 16777619; \
16 + __hash_value ^= (uint32_t) *__hash_source++; \
17 + } \
18 + __hash_value; \
19 +})
20 +
21 +static inline uint32_t simple_hash2(const char *name) {
22 + register unsigned char *s = (unsigned char *)name;
23 + register uint32_t hval = 0x811c9dc5;
24 + while (*s) {
25 + hval *= 16777619;
26 + hval ^= (uint32_t) *s++;
27 + }
28 + return hval;
29 +}
30 +
31 +static inline unsigned long long fast_strtoull(const char *s) {
32 + register unsigned long long n = 0;
33 + register char c;
34 + for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
35 + n *= 10;
36 + n += c - '0';
37 + // n = (n << 1) + (n << 3) + (c - '0');
38 + }
39 + return n;
40 +}
41 +
42 +static uint32_t cache_hash = 0;
43 +static uint32_t rss_hash = 0;
44 +static uint32_t rss_huge_hash = 0;
45 +static uint32_t mapped_file_hash = 0;
46 +static uint32_t writeback_hash = 0;
47 +static uint32_t dirty_hash = 0;
48 +static uint32_t swap_hash = 0;
49 +static uint32_t pgpgin_hash = 0;
50 +static uint32_t pgpgout_hash = 0;
51 +static uint32_t pgfault_hash = 0;
52 +static uint32_t pgmajfault_hash = 0;
53 +static uint32_t inactive_anon_hash = 0;
54 +static uint32_t active_anon_hash = 0;
55 +static uint32_t inactive_file_hash = 0;
56 +static uint32_t active_file_hash = 0;
57 +static uint32_t unevictable_hash = 0;
58 +static uint32_t hierarchical_memory_limit_hash = 0;
59 +static uint32_t total_cache_hash = 0;
60 +static uint32_t total_rss_hash = 0;
61 +static uint32_t total_rss_huge_hash = 0;
62 +static uint32_t total_mapped_file_hash = 0;
63 +static uint32_t total_writeback_hash = 0;
64 +static uint32_t total_dirty_hash = 0;
65 +static uint32_t total_swap_hash = 0;
66 +static uint32_t total_pgpgin_hash = 0;
67 +static uint32_t total_pgpgout_hash = 0;
68 +static uint32_t total_pgfault_hash = 0;
69 +static uint32_t total_pgmajfault_hash = 0;
70 +static uint32_t total_inactive_anon_hash = 0;
71 +static uint32_t total_active_anon_hash = 0;
72 +static uint32_t total_inactive_file_hash = 0;
73 +static uint32_t total_active_file_hash = 0;
74 +static uint32_t total_unevictable_hash = 0;
75 +
76 +char *strings[] = {
77 + "cache",
78 + "rss",
79 + "rss_huge",
80 + "mapped_file",
81 + "writeback",
82 + "dirty",
83 + "swap",
84 + "pgpgin",
85 + "pgpgout",
86 + "pgfault",
87 + "pgmajfault",
88 + "inactive_anon",
89 + "active_anon",
90 + "inactive_file",
91 + "active_file",
92 + "unevictable",
93 + "hierarchical_memory_limit",
94 + "total_cache",
95 + "total_rss",
96 + "total_rss_huge",
97 + "total_mapped_file",
98 + "total_writeback",
99 + "total_dirty",
100 + "total_swap",
101 + "total_pgpgin",
102 + "total_pgpgout",
103 + "total_pgfault",
104 + "total_pgmajfault",
105 + "total_inactive_anon",
106 + "total_active_anon",
107 + "total_inactive_file",
108 + "total_active_file",
109 + "total_unevictable",
110 + NULL
111 +};
112 +
113 +unsigned long long values1[12] = { 0 };
114 +unsigned long long values2[12] = { 0 };
115 +unsigned long long values3[12] = { 0 };
116 +unsigned long long values4[12] = { 0 };
117 +unsigned long long values5[12] = { 0 };
118 +unsigned long long values6[12] = { 0 };
119 +
120 +#define NUMBER1 "12345678901234"
121 +#define NUMBER2 "23456789012345"
122 +#define NUMBER3 "34567890123456"
123 +#define NUMBER4 "45678901234567"
124 +#define NUMBER5 "56789012345678"
125 +#define NUMBER6 "67890123456789"
126 +#define NUMBER7 "78901234567890"
127 +#define NUMBER8 "89012345678901"
128 +#define NUMBER9 "90123456789012"
129 +#define NUMBER10 "12345678901234"
130 +#define NUMBER11 "23456789012345"
131 +
132 +// simple system strcmp()
133 +void test1() {
134 + int i;
135 + for(i = 0; strings[i] ; i++) {
136 + char *s = strings[i];
137 +
138 + if(unlikely(!strcmp(s, "cache")))
139 + values1[i] = strtoull(NUMBER1, NULL, 10);
140 +
141 + else if(unlikely(!strcmp(s, "rss")))
142 + values1[i] = strtoull(NUMBER2, NULL, 10);
143 +
144 + else if(unlikely(!strcmp(s, "rss_huge")))
145 + values1[i] = strtoull(NUMBER3, NULL, 10);
146 +
147 + else if(unlikely(!strcmp(s, "mapped_file")))
148 + values1[i] = strtoull(NUMBER4, NULL, 10);
149 +
150 + else if(unlikely(!strcmp(s, "writeback")))
151 + values1[i] = strtoull(NUMBER5, NULL, 10);
152 +
153 + else if(unlikely(!strcmp(s, "dirty")))
154 + values1[i] = strtoull(NUMBER6, NULL, 10);
155 +
156 + else if(unlikely(!strcmp(s, "swap")))
157 + values1[i] = strtoull(NUMBER7, NULL, 10);
158 +
159 + else if(unlikely(!strcmp(s, "pgpgin")))
160 + values1[i] = strtoull(NUMBER8, NULL, 10);
161 +
162 + else if(unlikely(!strcmp(s, "pgpgout")))
163 + values1[i] = strtoull(NUMBER9, NULL, 10);
164 +
165 + else if(unlikely(!strcmp(s, "pgfault")))
166 + values1[i] = strtoull(NUMBER10, NULL, 10);
167 +
168 + else if(unlikely(!strcmp(s, "pgmajfault")))
169 + values1[i] = strtoull(NUMBER11, NULL, 10);
170 + }
171 +}
172 +
173 +// inline simple_hash() with system strtoull()
174 +void test2() {
175 + int i;
176 + for(i = 0; strings[i] ; i++) {
177 + char *s = strings[i];
178 + uint32_t hash = simple_hash2(s);
179 +
180 + if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
181 + values2[i] = strtoull(NUMBER1, NULL, 10);
182 +
183 + else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
184 + values2[i] = strtoull(NUMBER2, NULL, 10);
185 +
186 + else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
187 + values2[i] = strtoull(NUMBER3, NULL, 10);
188 +
189 + else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
190 + values2[i] = strtoull(NUMBER4, NULL, 10);
191 +
192 + else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
193 + values2[i] = strtoull(NUMBER5, NULL, 10);
194 +
195 + else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
196 + values2[i] = strtoull(NUMBER6, NULL, 10);
197 +
198 + else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
199 + values2[i] = strtoull(NUMBER7, NULL, 10);
200 +
201 + else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
202 + values2[i] = strtoull(NUMBER8, NULL, 10);
203 +
204 + else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
205 + values2[i] = strtoull(NUMBER9, NULL, 10);
206 +
207 + else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
208 + values2[i] = strtoull(NUMBER10, NULL, 10);
209 +
210 + else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
211 + values2[i] = strtoull(NUMBER11, NULL, 10);
212 + }
213 +}
214 +
215 +// statement expression simple_hash(), system strtoull()
216 +void test3() {
217 + int i;
218 + for(i = 0; strings[i] ; i++) {
219 + char *s = strings[i];
220 + uint32_t hash = simple_hash(s);
221 +
222 + if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
223 + values3[i] = strtoull(NUMBER1, NULL, 10);
224 +
225 + else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
226 + values3[i] = strtoull(NUMBER2, NULL, 10);
227 +
228 + else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
229 + values3[i] = strtoull(NUMBER3, NULL, 10);
230 +
231 + else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
232 + values3[i] = strtoull(NUMBER4, NULL, 10);
233 +
234 + else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
235 + values3[i] = strtoull(NUMBER5, NULL, 10);
236 +
237 + else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
238 + values3[i] = strtoull(NUMBER6, NULL, 10);
239 +
240 + else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
241 + values3[i] = strtoull(NUMBER7, NULL, 10);
242 +
243 + else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
244 + values3[i] = strtoull(NUMBER8, NULL, 10);
245 +
246 + else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
247 + values3[i] = strtoull(NUMBER9, NULL, 10);
248 +
249 + else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
250 + values3[i] = strtoull(NUMBER10, NULL, 10);
251 +
252 + else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
253 + values3[i] = strtoull(NUMBER11, NULL, 10);
254 + }
255 +}
256 +
257 +
258 +// inline simple_hash(), if-continue checks
259 +void test4() {
260 + int i;
261 + for(i = 0; strings[i] ; i++) {
262 + char *s = strings[i];
263 + uint32_t hash = simple_hash2(s);
264 +
265 + if(unlikely(hash == cache_hash && !strcmp(s, "cache"))) {
266 + values4[i] = strtoull(NUMBER1, NULL, 0);
267 + continue;
268 + }
269 +
270 + if(unlikely(hash == rss_hash && !strcmp(s, "rss"))) {
271 + values4[i] = strtoull(NUMBER2, NULL, 0);
272 + continue;
273 + }
274 +
275 + if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge"))) {
276 + values4[i] = strtoull(NUMBER3, NULL, 0);
277 + continue;
278 + }
279 +
280 + if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file"))) {
281 + values4[i] = strtoull(NUMBER4, NULL, 0);
282 + continue;
283 + }
284 +
285 + if(unlikely(hash == writeback_hash && !strcmp(s, "writeback"))) {
286 + values4[i] = strtoull(NUMBER5, NULL, 0);
287 + continue;
288 + }
289 +
290 + if(unlikely(hash == dirty_hash && !strcmp(s, "dirty"))) {
291 + values4[i] = strtoull(NUMBER6, NULL, 0);
292 + continue;
293 + }
294 +
295 + if(unlikely(hash == swap_hash && !strcmp(s, "swap"))) {
296 + values4[i] = strtoull(NUMBER7, NULL, 0);
297 + continue;
298 + }
299 +
300 + if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin"))) {
301 + values4[i] = strtoull(NUMBER8, NULL, 0);
302 + continue;
303 + }
304 +
305 + if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout"))) {
306 + values4[i] = strtoull(NUMBER9, NULL, 0);
307 + continue;
308 + }
309 +
310 + if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault"))) {
311 + values4[i] = strtoull(NUMBER10, NULL, 0);
312 + continue;
313 + }
314 +
315 + if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))) {
316 + values4[i] = strtoull(NUMBER11, NULL, 0);
317 + continue;
318 + }
319 + }
320 +}
321 +
322 +// inline simple_hash(), if-else-if-else-if (netdata default)
323 +void test5() {
324 + int i;
325 + for(i = 0; strings[i] ; i++) {
326 + char *s = strings[i];
327 + uint32_t hash = simple_hash2(s);
328 +
329 + if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
330 + values5[i] = fast_strtoull(NUMBER1);
331 +
332 + else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
333 + values5[i] = fast_strtoull(NUMBER2);
334 +
335 + else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
336 + values5[i] = fast_strtoull(NUMBER3);
337 +
338 + else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
339 + values5[i] = fast_strtoull(NUMBER4);
340 +
341 + else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
342 + values5[i] = fast_strtoull(NUMBER5);
343 +
344 + else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
345 + values5[i] = fast_strtoull(NUMBER6);
346 +
347 + else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
348 + values5[i] = fast_strtoull(NUMBER7);
349 +
350 + else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
351 + values5[i] = fast_strtoull(NUMBER8);
352 +
353 + else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
354 + values5[i] = fast_strtoull(NUMBER9);
355 +
356 + else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
357 + values5[i] = fast_strtoull(NUMBER10);
358 +
359 + else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
360 + values5[i] = fast_strtoull(NUMBER11);
361 + }
362 +}
363 +
364 +// ----------------------------------------------------------------------------
365 +
366 +struct entry {
367 + char *name;
368 + uint32_t hash;
369 + int found;
370 + void (*func)(void *data1, void *data2);
371 + void *data1;
372 + void *data2;
373 + struct entry *prev, *next;
374 +};
375 +
376 +struct base {
377 + int iteration;
378 + int registered;
379 + int wanted;
380 + int found;
381 + struct entry *entries, *last;
382 +};
383 +
384 +static inline void callback(void *data1, void *data2) {
385 + char *string = data1;
386 + unsigned long long *value = data2;
387 + *value = fast_strtoull(string);
388 +}
389 +
390 +
391 +static inline struct base *entry(struct base *base, const char *name, void *data1, void *data2, void (*func)(void *, void *)) {
392 + if(!base)
393 + base = calloc(1, sizeof(struct base));
394 +
395 + struct entry *e = malloc(sizeof(struct entry));
396 + e->name = strdup(name);
397 + e->hash = simple_hash2(e->name);
398 + e->data1 = data1;
399 + e->data2 = data2;
400 + e->func = func;
401 + e->prev = NULL;
402 + e->next = base->entries;
403 +
404 + if(base->entries) base->entries->prev = e;
405 + else base->last = e;
406 +
407 + base->entries = e;
408 + base->registered++;
409 + base->wanted = base->registered;
410 +
411 + return base;
412 +}
413 +
414 +static inline int check(struct base *base, const char *s) {
415 + uint32_t hash = simple_hash2(s);
416 +
417 + if(likely(hash == base->last->hash && !strcmp(s, base->last->name))) {
418 + base->last->found = 1;
419 + base->found++;
420 + if(base->last->func) base->last->func(base->last->data1, base->last->data2);
421 + base->last = base->last->next;
422 +
423 + if(!base->last)
424 + base->last = base->entries;
425 +
426 + if(base->found == base->registered)
427 + return 1;
428 +
429 + return 0;
430 + }
431 +
432 + // find it
433 + struct entry *e;
434 + for(e = base->entries; e ; e = e->next)
435 + if(e->hash == hash && !strcmp(e->name, s))
436 + break;
437 +
438 + if(e == base->last) {
439 + printf("ERROR\n");
440 + exit(1);
441 + }
442 +
443 + if(e) {
444 + // found
445 +
446 + // run it
447 + if(e->func) e->func(e->data1, e->data2);
448 +
449 + // unlink it
450 + if(e->next) e->next->prev = e->prev;
451 + if(e->prev) e->prev->next = e->next;
452 +
453 + if(base->entries == e)
454 + base->entries = e->next;
455 + }
456 + else {
457 + // not found
458 +
459 + // create it
460 + e = calloc(1, sizeof(struct entry));
461 + e->name = strdup(s);
462 + e->hash = hash;
463 + }
464 +
465 + // link it here
466 + e->next = base->last;
467 + if(base->last) {
468 + e->prev = base->last->prev;
469 + base->last->prev = e;
470 +
471 + if(base->entries == base->last)
472 + base->entries = e;
473 + }
474 + else
475 + e->prev = NULL;
476 +
477 + if(e->prev)
478 + e->prev->next = e;
479 +
480 + base->last = e->next;
481 + if(!base->last)
482 + base->last = base->entries;
483 +
484 + e->found = 1;
485 + base->found++;
486 +
487 + if(base->found == base->registered)
488 + return 1;
489 +
490 + printf("relinked '%s' after '%s' and before '%s': ", e->name, e->prev?e->prev->name:"NONE", e->next?e->next->name:"NONE");
491 + for(e = base->entries; e ; e = e->next) printf("%s ", e->name);
492 + printf("\n");
493 +
494 + return 0;
495 +}
496 +
497 +static inline void begin(struct base *base) {
498 +
499 + if(unlikely(base->iteration % 60) == 1) {
500 + base->wanted = 0;
501 + struct entry *e;
502 + for(e = base->entries; e ; e = e->next)
503 + if(e->found) base->wanted++;
504 + }
505 +
506 + base->iteration++;
507 + base->last = base->entries;
508 + base->found = 0;
509 +}
510 +
511 +void test6() {
512 +
513 + static struct base *base = NULL;
514 +
515 + if(unlikely(!base)) {
516 + base = entry(base, "cache", NUMBER1, &values6[0], callback);
517 + base = entry(base, "rss", NUMBER2, &values6[1], callback);
518 + base = entry(base, "rss_huge", NUMBER3, &values6[2], callback);
519 + base = entry(base, "mapped_file", NUMBER4, &values6[3], callback);
520 + base = entry(base, "writeback", NUMBER5, &values6[4], callback);
521 + base = entry(base, "dirty", NUMBER6, &values6[5], callback);
522 + base = entry(base, "swap", NUMBER7, &values6[6], callback);
523 + base = entry(base, "pgpgin", NUMBER8, &values6[7], callback);
524 + base = entry(base, "pgpgout", NUMBER9, &values6[8], callback);
525 + base = entry(base, "pgfault", NUMBER10, &values6[9], callback);
526 + base = entry(base, "pgmajfault", NUMBER11, &values6[10], callback);
527 + }
528 +
529 + begin(base);
530 +
531 + int i;
532 + for(i = 0; strings[i] ; i++) {
533 + if(check(base, strings[i]))
534 + break;
535 + }
536 +}
537 +
538 +// ----------------------------------------------------------------------------
539 +
540 +
541 +// ==============
542 +// --- Poor man cycle counting.
543 +static unsigned long tsc;
544 +
545 +static void begin_tsc(void)
546 +{
547 + unsigned long a, d;
548 + asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
549 + tsc = ((unsigned long)d << 32) | (unsigned long)a;
550 +}
551 +
552 +static unsigned long end_tsc(void)
553 +{
554 + unsigned long a, d;
555 + asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
556 + return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
557 +}
558 +// ===============
559 +
560 +static unsigned long long clk;
561 +
562 +static void begin_clock() {
563 + struct timeval tv;
564 + if(unlikely(gettimeofday(&tv, NULL) == -1))
565 + return;
566 + clk = tv.tv_sec * 1000000 + tv.tv_usec;
567 +}
568 +
569 +static unsigned long long end_clock() {
570 + struct timeval tv;
571 + if(unlikely(gettimeofday(&tv, NULL) == -1))
572 + return -1;
573 + return clk = tv.tv_sec * 1000000 + tv.tv_usec - clk;
574 +}
575 +
576 +void main(void)
577 +{
578 + cache_hash = simple_hash("cache");
579 + rss_hash = simple_hash("rss");
580 + rss_huge_hash = simple_hash("rss_huge");
581 + mapped_file_hash = simple_hash("mapped_file");
582 + writeback_hash = simple_hash("writeback");
583 + dirty_hash = simple_hash("dirty");
584 + swap_hash = simple_hash("swap");
585 + pgpgin_hash = simple_hash("pgpgin");
586 + pgpgout_hash = simple_hash("pgpgout");
587 + pgfault_hash = simple_hash("pgfault");
588 + pgmajfault_hash = simple_hash("pgmajfault");
589 + inactive_anon_hash = simple_hash("inactive_anon");
590 + active_anon_hash = simple_hash("active_anon");
591 + inactive_file_hash = simple_hash("inactive_file");
592 + active_file_hash = simple_hash("active_file");
593 + unevictable_hash = simple_hash("unevictable");
594 + hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
595 + total_cache_hash = simple_hash("total_cache");
596 + total_rss_hash = simple_hash("total_rss");
597 + total_rss_huge_hash = simple_hash("total_rss_huge");
598 + total_mapped_file_hash = simple_hash("total_mapped_file");
599 + total_writeback_hash = simple_hash("total_writeback");
600 + total_dirty_hash = simple_hash("total_dirty");
601 + total_swap_hash = simple_hash("total_swap");
602 + total_pgpgin_hash = simple_hash("total_pgpgin");
603 + total_pgpgout_hash = simple_hash("total_pgpgout");
604 + total_pgfault_hash = simple_hash("total_pgfault");
605 + total_pgmajfault_hash = simple_hash("total_pgmajfault");
606 + total_inactive_anon_hash = simple_hash("total_inactive_anon");
607 + total_active_anon_hash = simple_hash("total_active_anon");
608 + total_inactive_file_hash = simple_hash("total_inactive_file");
609 + total_active_file_hash = simple_hash("total_active_file");
610 + total_unevictable_hash = simple_hash("total_unevictable");
611 +
612 + // cache functions
613 + (void)simple_hash2("hello world");
614 + (void)strcmp("1", "2");
615 + (void)strtoull("123", NULL, 0);
616 +
617 + unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0;
618 + unsigned long max = 200000;
619 +
620 + begin_clock();
621 + for(i = 0; i <= max ;i++) test1();
622 + c1 = end_clock();
623 +
624 + begin_clock();
625 + for(i = 0; i <= max ;i++) test2();
626 + c2 = end_clock();
627 +
628 + begin_clock();
629 + for(i = 0; i <= max ;i++) test3();
630 + c3 = end_clock();
631 +
632 + begin_clock();
633 + for(i = 0; i <= max ;i++) test4();
634 + c4 = end_clock();
635 +
636 + begin_clock();
637 + for(i = 0; i <= max ;i++) test5();
638 + c5 = end_clock();
639 +
640 + begin_clock();
641 + for(i = 0; i <= max ;i++) test6();
642 + c6 = end_clock();
643 +
644 + for(i = 0; i < 11 ; i++)
645 + printf("value %lu: %llu %llu %llu %llu %llu %llu\n", i, values1[i], values2[i], values3[i], values4[i], values5[i], values6[i]);
646 +
647 + printf("\n\nRESULTS\n");
648 + printf("test1() in %lu usecs: simple system strcmp().\n"
649 + "test2() in %lu usecs: inline simple_hash() with system strtoull().\n"
650 + "test3() in %lu usecs: statement expression simple_hash(), system strtoull().\n"
651 + "test4() in %lu usecs: inline simple_hash(), if-continue checks.\n"
652 + "test5() in %lu usecs: inline simple_hash(), if-else-if-else-if (netdata default).\n"
653 + "test6() in %lu usecs: adaptive re-sortable array (wow!)\n"
654 + , c1
655 + , c2
656 + , c3
657 + , c4
658 + , c5
659 + , c6
660 + );
661 +
662 +}
profile/benchmark-procfile-parser.c new
+328
@@ -0,0 +1,328 @@
1 +#include "config.h"
2 +#include "common.h"
3 +#include "clocks.h"
4 +
5 +void netdata_cleanup_and_exit(int ret) {
6 + exit(ret);
7 +}
8 +
9 +#define PF_PREFIX "PROCFILE"
10 +#define PFWORDS_INCREASE_STEP 200
11 +#define PFLINES_INCREASE_STEP 10
12 +#define PROCFILE_INCREMENT_BUFFER 512
13 +extern size_t procfile_max_lines;
14 +extern size_t procfile_max_words;
15 +extern size_t procfile_max_allocation;
16 +
17 +
18 +static inline void pflines_reset(pflines *fl) {
19 + // debug(D_PROCFILE, PF_PREFIX ": reseting lines");
20 +
21 + fl->len = 0;
22 +}
23 +
24 +static inline void pflines_free(pflines *fl) {
25 + // debug(D_PROCFILE, PF_PREFIX ": freeing lines");
26 +
27 + freez(fl);
28 +}
29 +
30 +static inline void pfwords_reset(pfwords *fw) {
31 + // debug(D_PROCFILE, PF_PREFIX ": reseting words");
32 + fw->len = 0;
33 +}
34 +
35 +
36 +static inline void pfwords_add(procfile *ff, char *str) {
37 + // debug(D_PROCFILE, PF_PREFIX ": adding word No %d: '%s'", fw->len, str);
38 +
39 + pfwords *fw = ff->words;
40 + if(unlikely(fw->len == fw->size)) {
41 + // debug(D_PROCFILE, PF_PREFIX ": expanding words");
42 +
43 + ff->words = fw = reallocz(fw, sizeof(pfwords) + (fw->size + PFWORDS_INCREASE_STEP) * sizeof(char *));
44 + fw->size += PFWORDS_INCREASE_STEP;
45 + }
46 +
47 + fw->words[fw->len++] = str;
48 +}
49 +
50 +NEVERNULL
51 +static inline size_t *pflines_add(procfile *ff) {
52 + // debug(D_PROCFILE, PF_PREFIX ": adding line %d at word %d", fl->len, first_word);
53 +
54 + pflines *fl = ff->lines;
55 + if(unlikely(fl->len == fl->size)) {
56 + // debug(D_PROCFILE, PF_PREFIX ": expanding lines");
57 +
58 + ff->lines = fl = reallocz(fl, sizeof(pflines) + (fl->size + PFLINES_INCREASE_STEP) * sizeof(ffline));
59 + fl->size += PFLINES_INCREASE_STEP;
60 + }
61 +
62 + ffline *ffl = &fl->lines[fl->len++];
63 + ffl->words = 0;
64 + ffl->first = ff->words->len;
65 +
66 + return &ffl->words;
67 +}
68 +
69 +
70 +NOINLINE
71 +static void procfile_parser(procfile *ff) {
72 + // debug(D_PROCFILE, PF_PREFIX ": Parsing file '%s'", ff->filename);
73 +
74 + char *s = ff->data // our current position
75 + , *e = &ff->data[ff->len] // the terminating null
76 + , *t = ff->data; // the first character of a word (or quoted / parenthesized string)
77 +
78 + // the look up array to find our type of character
79 + PF_CHAR_TYPE *separators = ff->separators;
80 +
81 + char quote = 0; // the quote character - only when in quoted string
82 + size_t opened = 0; // counts the number of open parenthesis
83 +
84 + size_t *line_words = pflines_add(ff);
85 +
86 + while(s < e) {
87 + PF_CHAR_TYPE ct = separators[(unsigned char)(*s)];
88 +
89 + // this is faster than a switch()
90 + // read more here: http://lazarenko.me/switch/
91 + switch(ct) {
92 + case PF_CHAR_IS_SEPARATOR:
93 + if(!quote && !opened) {
94 + if (s != t) {
95 + // separator, but we have word before it
96 + *s = '\0';
97 + pfwords_add(ff, t);
98 + (*line_words)++;
99 + }
100 + t = s + 1;
101 + }
102 + // fallthrough
103 +
104 + case PF_CHAR_IS_WORD:
105 + s++;
106 + break;
107 +
108 +
109 + case PF_CHAR_IS_NEWLINE:
110 + // end of line
111 +
112 + *s = '\0';
113 + pfwords_add(ff, t);
114 + (*line_words)++;
115 + t = ++s;
116 +
117 + // debug(D_PROCFILE, PF_PREFIX ": ended line %d with %d words", l, ff->lines->lines[l].words);
118 +
119 + line_words = pflines_add(ff);
120 + break;
121 +
122 + case PF_CHAR_IS_QUOTE:
123 + if(unlikely(!quote && s == t)) {
124 + // quote opened at the beginning
125 + quote = *s;
126 + t = ++s;
127 + }
128 + else if(unlikely(quote && quote == *s)) {
129 + // quote closed
130 + quote = 0;
131 +
132 + *s = '\0';
133 + pfwords_add(ff, t);
134 + (*line_words)++;
135 + t = ++s;
136 + }
137 + else
138 + s++;
139 + break;
140 +
141 + case PF_CHAR_IS_OPEN:
142 + if(s == t) {
143 + opened++;
144 + t = ++s;
145 + }
146 + else if(opened) {
147 + opened++;
148 + s++;
149 + }
150 + else
151 + s++;
152 + break;
153 +
154 + case PF_CHAR_IS_CLOSE:
155 + if(opened) {
156 + opened--;
157 +
158 + if(!opened) {
159 + *s = '\0';
160 + pfwords_add(ff, t);
161 + (*line_words)++;
162 + t = ++s;
163 + }
164 + else
165 + s++;
166 + }
167 + else
168 + s++;
169 + break;
170 +
171 + default:
172 + fatal("Internal Error: procfile_readall() does not handle all the cases.");
173 + }
174 + }
175 +
176 + if(likely(s > t && t < e)) {
177 + // the last word
178 + if(unlikely(ff->len >= ff->size)) {
179 + // we are going to loose the last byte
180 + s = &ff->data[ff->size - 1];
181 + }
182 +
183 + *s = '\0';
184 + pfwords_add(ff, t);
185 + (*line_words)++;
186 + // t = ++s;
187 + }
188 +}
189 +
190 +
191 +procfile *procfile_readall1(procfile *ff) {
192 + // debug(D_PROCFILE, PF_PREFIX ": Reading file '%s'.", ff->filename);
193 +
194 + ff->len = 0; // zero the used size
195 + ssize_t r = 1; // read at least once
196 + while(r > 0) {
197 + ssize_t s = ff->len;
198 + ssize_t x = ff->size - s;
199 +
200 + if(unlikely(!x)) {
201 + debug(D_PROCFILE, PF_PREFIX ": Expanding data buffer for file '%s'.", procfile_filename(ff));
202 + ff = reallocz(ff, sizeof(procfile) + ff->size + PROCFILE_INCREMENT_BUFFER);
203 + ff->size += PROCFILE_INCREMENT_BUFFER;
204 + }
205 +
206 + debug(D_PROCFILE, "Reading file '%s', from position %zd with length %zd", procfile_filename(ff), s, (ssize_t)(ff->size - s));
207 + r = read(ff->fd, &ff->data[s], ff->size - s);
208 + if(unlikely(r == -1)) {
209 + if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot read from file '%s' on fd %d", procfile_filename(ff), ff->fd);
210 + procfile_close(ff);
211 + return NULL;
212 + }
213 +
214 + ff->len += r;
215 + }
216 +
217 + // debug(D_PROCFILE, "Rewinding file '%s'", ff->filename);
218 + if(unlikely(lseek(ff->fd, 0, SEEK_SET) == -1)) {
219 + if(unlikely(!(ff->flags & PROCFILE_FLAG_NO_ERROR_ON_FILE_IO))) error(PF_PREFIX ": Cannot rewind on file '%s'.", procfile_filename(ff));
220 + procfile_close(ff);
221 + return NULL;
222 + }
223 +
224 + pflines_reset(ff->lines);
225 + pfwords_reset(ff->words);
226 + procfile_parser(ff);
227 +
228 + if(unlikely(procfile_adaptive_initial_allocation)) {
229 + if(unlikely(ff->len > procfile_max_allocation)) procfile_max_allocation = ff->len;
230 + if(unlikely(ff->lines->len > procfile_max_lines)) procfile_max_lines = ff->lines->len;
231 + if(unlikely(ff->words->len > procfile_max_words)) procfile_max_words = ff->words->len;
232 + }
233 +
234 + // debug(D_PROCFILE, "File '%s' updated.", ff->filename);
235 + return ff;
236 +}
237 +
238 +
239 +
240 +
241 +
242 +
243 +
244 +
245 +// ==============
246 +// --- Poor man cycle counting.
247 +static unsigned long tsc;
248 +
249 +void begin_tsc(void)
250 +{
251 + unsigned long a, d;
252 + asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
253 + tsc = ((unsigned long)d << 32) | (unsigned long)a;
254 +}
255 +
256 +unsigned long end_tsc(void)
257 +{
258 + unsigned long a, d;
259 + asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
260 + return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
261 +}
262 +// ==============
263 +
264 +
265 +unsigned long test_netdata_internal(void) {
266 + static procfile *ff = NULL;
267 +
268 + ff = procfile_reopen(ff, "/proc/self/status", " \t:,-()/", PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
269 + if(!ff) {
270 + fprintf(stderr, "Failed to open filename\n");
271 + exit(1);
272 + }
273 +
274 + begin_tsc();
275 + ff = procfile_readall(ff);
276 + unsigned long c = end_tsc();
277 +
278 + if(!ff) {
279 + fprintf(stderr, "Failed to read filename\n");
280 + exit(1);
281 + }
282 +
283 + return c;
284 +}
285 +
286 +unsigned long test_method1(void) {
287 + static procfile *ff = NULL;
288 +
289 + ff = procfile_reopen(ff, "/proc/self/status", " \t:,-()/", PROCFILE_FLAG_NO_ERROR_ON_FILE_IO);
290 + if(!ff) {
291 + fprintf(stderr, "Failed to open filename\n");
292 + exit(1);
293 + }
294 +
295 + begin_tsc();
296 + ff = procfile_readall1(ff);
297 + unsigned long c = end_tsc();
298 +
299 + if(!ff) {
300 + fprintf(stderr, "Failed to read filename\n");
301 + exit(1);
302 + }
303 +
304 + return c;
305 +}
306 +
307 +//--- Test
308 +int main(int argc, char **argv)
309 +{
310 + (void)argc; (void)argv;
311 +
312 + int i, max = 1000000;
313 +
314 + unsigned long c1 = 0;
315 + test_netdata_internal();
316 + for(i = 0; i < max ; i++)
317 + c1 += test_netdata_internal();
318 +
319 + unsigned long c2 = 0;
320 + test_method1();
321 + for(i = 0; i < max ; i++)
322 + c2 += test_method1();
323 +
324 + printf("netdata internal: completed in %lu cycles, %lu cycles per read, %0.2f %%.\n", c1, c1 / max, (float)c1 * 100.0 / (float)c1);
325 + printf("method1 : completed in %lu cycles, %lu cycles per read, %0.2f %%.\n", c2, c2 / max, (float)c2 * 100.0 / (float)c1);
326 +
327 + return 0;
328 +}
profile/benchmark-strcmp.c new
+662
@@ -0,0 +1,662 @@
1 +#include <stdio.h>
2 +#include <inttypes.h>
3 +#include <string.h>
4 +#include <stdlib.h>
5 +#include <ctype.h>
6 +#include <sys/time.h>
7 +
8 +#define likely(x) __builtin_expect(!!(x), 1)
9 +#define unlikely(x) __builtin_expect(!!(x), 0)
10 +
11 +#define simple_hash(name) ({ \
12 + register unsigned char *__hash_source = (unsigned char *)(name); \
13 + register uint32_t __hash_value = 0x811c9dc5; \
14 + while (*__hash_source) { \
15 + __hash_value *= 16777619; \
16 + __hash_value ^= (uint32_t) *__hash_source++; \
17 + } \
18 + __hash_value; \
19 +})
20 +
21 +static inline uint32_t simple_hash2(const char *name) {
22 + register unsigned char *s = (unsigned char *)name;
23 + register uint32_t hval = 0x811c9dc5;
24 + while (*s) {
25 + hval *= 16777619;
26 + hval ^= (uint32_t) *s++;
27 + }
28 + return hval;
29 +}
30 +
31 +static inline unsigned long long fast_strtoull(const char *s) {
32 + register unsigned long long n = 0;
33 + register char c;
34 + for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
35 + n *= 10;
36 + n += c - '0';
37 + // n = (n << 1) + (n << 3) + (c - '0');
38 + }
39 + return n;
40 +}
41 +
42 +static uint32_t cache_hash = 0;
43 +static uint32_t rss_hash = 0;
44 +static uint32_t rss_huge_hash = 0;
45 +static uint32_t mapped_file_hash = 0;
46 +static uint32_t writeback_hash = 0;
47 +static uint32_t dirty_hash = 0;
48 +static uint32_t swap_hash = 0;
49 +static uint32_t pgpgin_hash = 0;
50 +static uint32_t pgpgout_hash = 0;
51 +static uint32_t pgfault_hash = 0;
52 +static uint32_t pgmajfault_hash = 0;
53 +static uint32_t inactive_anon_hash = 0;
54 +static uint32_t active_anon_hash = 0;
55 +static uint32_t inactive_file_hash = 0;
56 +static uint32_t active_file_hash = 0;
57 +static uint32_t unevictable_hash = 0;
58 +static uint32_t hierarchical_memory_limit_hash = 0;
59 +static uint32_t total_cache_hash = 0;
60 +static uint32_t total_rss_hash = 0;
61 +static uint32_t total_rss_huge_hash = 0;
62 +static uint32_t total_mapped_file_hash = 0;
63 +static uint32_t total_writeback_hash = 0;
64 +static uint32_t total_dirty_hash = 0;
65 +static uint32_t total_swap_hash = 0;
66 +static uint32_t total_pgpgin_hash = 0;
67 +static uint32_t total_pgpgout_hash = 0;
68 +static uint32_t total_pgfault_hash = 0;
69 +static uint32_t total_pgmajfault_hash = 0;
70 +static uint32_t total_inactive_anon_hash = 0;
71 +static uint32_t total_active_anon_hash = 0;
72 +static uint32_t total_inactive_file_hash = 0;
73 +static uint32_t total_active_file_hash = 0;
74 +static uint32_t total_unevictable_hash = 0;
75 +
76 +char *strings[] = {
77 + "cache",
78 + "rss",
79 + "rss_huge",
80 + "mapped_file",
81 + "writeback",
82 + "dirty",
83 + "swap",
84 + "pgpgin",
85 + "pgpgout",
86 + "pgfault",
87 + "pgmajfault",
88 + "inactive_anon",
89 + "active_anon",
90 + "inactive_file",
91 + "active_file",
92 + "unevictable",
93 + "hierarchical_memory_limit",
94 + "total_cache",
95 + "total_rss",
96 + "total_rss_huge",
97 + "total_mapped_file",
98 + "total_writeback",
99 + "total_dirty",
100 + "total_swap",
101 + "total_pgpgin",
102 + "total_pgpgout",
103 + "total_pgfault",
104 + "total_pgmajfault",
105 + "total_inactive_anon",
106 + "total_active_anon",
107 + "total_inactive_file",
108 + "total_active_file",
109 + "total_unevictable",
110 + NULL
111 +};
112 +
113 +unsigned long long values1[12] = { 0 };
114 +unsigned long long values2[12] = { 0 };
115 +unsigned long long values3[12] = { 0 };
116 +unsigned long long values4[12] = { 0 };
117 +unsigned long long values5[12] = { 0 };
118 +unsigned long long values6[12] = { 0 };
119 +
120 +#define NUMBER1 "12345678901234"
121 +#define NUMBER2 "23456789012345"
122 +#define NUMBER3 "34567890123456"
123 +#define NUMBER4 "45678901234567"
124 +#define NUMBER5 "56789012345678"
125 +#define NUMBER6 "67890123456789"
126 +#define NUMBER7 "78901234567890"
127 +#define NUMBER8 "89012345678901"
128 +#define NUMBER9 "90123456789012"
129 +#define NUMBER10 "12345678901234"
130 +#define NUMBER11 "23456789012345"
131 +
132 +// simple system strcmp()
133 +void test1() {
134 + int i;
135 + for(i = 0; strings[i] ; i++) {
136 + char *s = strings[i];
137 +
138 + if(unlikely(!strcmp(s, "cache")))
139 + values1[i] = strtoull(NUMBER1, NULL, 10);
140 +
141 + else if(unlikely(!strcmp(s, "rss")))
142 + values1[i] = strtoull(NUMBER2, NULL, 10);
143 +
144 + else if(unlikely(!strcmp(s, "rss_huge")))
145 + values1[i] = strtoull(NUMBER3, NULL, 10);
146 +
147 + else if(unlikely(!strcmp(s, "mapped_file")))
148 + values1[i] = strtoull(NUMBER4, NULL, 10);
149 +
150 + else if(unlikely(!strcmp(s, "writeback")))
151 + values1[i] = strtoull(NUMBER5, NULL, 10);
152 +
153 + else if(unlikely(!strcmp(s, "dirty")))
154 + values1[i] = strtoull(NUMBER6, NULL, 10);
155 +
156 + else if(unlikely(!strcmp(s, "swap")))
157 + values1[i] = strtoull(NUMBER7, NULL, 10);
158 +
159 + else if(unlikely(!strcmp(s, "pgpgin")))
160 + values1[i] = strtoull(NUMBER8, NULL, 10);
161 +
162 + else if(unlikely(!strcmp(s, "pgpgout")))
163 + values1[i] = strtoull(NUMBER9, NULL, 10);
164 +
165 + else if(unlikely(!strcmp(s, "pgfault")))
166 + values1[i] = strtoull(NUMBER10, NULL, 10);
167 +
168 + else if(unlikely(!strcmp(s, "pgmajfault")))
169 + values1[i] = strtoull(NUMBER11, NULL, 10);
170 + }
171 +}
172 +
173 +// inline simple_hash() with system strtoull()
174 +void test2() {
175 + int i;
176 + for(i = 0; strings[i] ; i++) {
177 + char *s = strings[i];
178 + uint32_t hash = simple_hash2(s);
179 +
180 + if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
181 + values2[i] = strtoull(NUMBER1, NULL, 10);
182 +
183 + else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
184 + values2[i] = strtoull(NUMBER2, NULL, 10);
185 +
186 + else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
187 + values2[i] = strtoull(NUMBER3, NULL, 10);
188 +
189 + else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
190 + values2[i] = strtoull(NUMBER4, NULL, 10);
191 +
192 + else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
193 + values2[i] = strtoull(NUMBER5, NULL, 10);
194 +
195 + else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
196 + values2[i] = strtoull(NUMBER6, NULL, 10);
197 +
198 + else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
199 + values2[i] = strtoull(NUMBER7, NULL, 10);
200 +
201 + else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
202 + values2[i] = strtoull(NUMBER8, NULL, 10);
203 +
204 + else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
205 + values2[i] = strtoull(NUMBER9, NULL, 10);
206 +
207 + else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
208 + values2[i] = strtoull(NUMBER10, NULL, 10);
209 +
210 + else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
211 + values2[i] = strtoull(NUMBER11, NULL, 10);
212 + }
213 +}
214 +
215 +// statement expression simple_hash(), system strtoull()
216 +void test3() {
217 + int i;
218 + for(i = 0; strings[i] ; i++) {
219 + char *s = strings[i];
220 + uint32_t hash = simple_hash(s);
221 +
222 + if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
223 + values3[i] = strtoull(NUMBER1, NULL, 10);
224 +
225 + else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
226 + values3[i] = strtoull(NUMBER2, NULL, 10);
227 +
228 + else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
229 + values3[i] = strtoull(NUMBER3, NULL, 10);
230 +
231 + else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
232 + values3[i] = strtoull(NUMBER4, NULL, 10);
233 +
234 + else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
235 + values3[i] = strtoull(NUMBER5, NULL, 10);
236 +
237 + else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
238 + values3[i] = strtoull(NUMBER6, NULL, 10);
239 +
240 + else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
241 + values3[i] = strtoull(NUMBER7, NULL, 10);
242 +
243 + else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
244 + values3[i] = strtoull(NUMBER8, NULL, 10);
245 +
246 + else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
247 + values3[i] = strtoull(NUMBER9, NULL, 10);
248 +
249 + else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
250 + values3[i] = strtoull(NUMBER10, NULL, 10);
251 +
252 + else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
253 + values3[i] = strtoull(NUMBER11, NULL, 10);
254 + }
255 +}
256 +
257 +
258 +// inline simple_hash(), if-continue checks
259 +void test4() {
260 + int i;
261 + for(i = 0; strings[i] ; i++) {
262 + char *s = strings[i];
263 + uint32_t hash = simple_hash2(s);
264 +
265 + if(unlikely(hash == cache_hash && !strcmp(s, "cache"))) {
266 + values4[i] = strtoull(NUMBER1, NULL, 0);
267 + continue;
268 + }
269 +
270 + if(unlikely(hash == rss_hash && !strcmp(s, "rss"))) {
271 + values4[i] = strtoull(NUMBER2, NULL, 0);
272 + continue;
273 + }
274 +
275 + if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge"))) {
276 + values4[i] = strtoull(NUMBER3, NULL, 0);
277 + continue;
278 + }
279 +
280 + if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file"))) {
281 + values4[i] = strtoull(NUMBER4, NULL, 0);
282 + continue;
283 + }
284 +
285 + if(unlikely(hash == writeback_hash && !strcmp(s, "writeback"))) {
286 + values4[i] = strtoull(NUMBER5, NULL, 0);
287 + continue;
288 + }
289 +
290 + if(unlikely(hash == dirty_hash && !strcmp(s, "dirty"))) {
291 + values4[i] = strtoull(NUMBER6, NULL, 0);
292 + continue;
293 + }
294 +
295 + if(unlikely(hash == swap_hash && !strcmp(s, "swap"))) {
296 + values4[i] = strtoull(NUMBER7, NULL, 0);
297 + continue;
298 + }
299 +
300 + if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin"))) {
301 + values4[i] = strtoull(NUMBER8, NULL, 0);
302 + continue;
303 + }
304 +
305 + if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout"))) {
306 + values4[i] = strtoull(NUMBER9, NULL, 0);
307 + continue;
308 + }
309 +
310 + if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault"))) {
311 + values4[i] = strtoull(NUMBER10, NULL, 0);
312 + continue;
313 + }
314 +
315 + if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))) {
316 + values4[i] = strtoull(NUMBER11, NULL, 0);
317 + continue;
318 + }
319 + }
320 +}
321 +
322 +// inline simple_hash(), if-else-if-else-if (netdata default)
323 +void test5() {
324 + int i;
325 + for(i = 0; strings[i] ; i++) {
326 + char *s = strings[i];
327 + uint32_t hash = simple_hash2(s);
328 +
329 + if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
330 + values5[i] = fast_strtoull(NUMBER1);
331 +
332 + else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
333 + values5[i] = fast_strtoull(NUMBER2);
334 +
335 + else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
336 + values5[i] = fast_strtoull(NUMBER3);
337 +
338 + else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
339 + values5[i] = fast_strtoull(NUMBER4);
340 +
341 + else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
342 + values5[i] = fast_strtoull(NUMBER5);
343 +
344 + else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
345 + values5[i] = fast_strtoull(NUMBER6);
346 +
347 + else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
348 + values5[i] = fast_strtoull(NUMBER7);
349 +
350 + else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
351 + values5[i] = fast_strtoull(NUMBER8);
352 +
353 + else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
354 + values5[i] = fast_strtoull(NUMBER9);
355 +
356 + else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
357 + values5[i] = fast_strtoull(NUMBER10);
358 +
359 + else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
360 + values5[i] = fast_strtoull(NUMBER11);
361 + }
362 +}
363 +
364 +// ----------------------------------------------------------------------------
365 +
366 +struct entry {
367 + char *name;
368 + uint32_t hash;
369 + int found;
370 + void (*func)(void *data1, void *data2);
371 + void *data1;
372 + void *data2;
373 + struct entry *prev, *next;
374 +};
375 +
376 +struct base {
377 + int iteration;
378 + int registered;
379 + int wanted;
380 + int found;
381 + struct entry *entries, *last;
382 +};
383 +
384 +static inline void callback(void *data1, void *data2) {
385 + char *string = data1;
386 + unsigned long long *value = data2;
387 + *value = fast_strtoull(string);
388 +}
389 +
390 +
391 +static inline struct base *entry(struct base *base, const char *name, void *data1, void *data2, void (*func)(void *, void *)) {
392 + if(!base)
393 + base = calloc(1, sizeof(struct base));
394 +
395 + struct entry *e = malloc(sizeof(struct entry));
396 + e->name = strdup(name);
397 + e->hash = simple_hash2(e->name);
398 + e->data1 = data1;
399 + e->data2 = data2;
400 + e->func = func;
401 + e->prev = NULL;
402 + e->next = base->entries;
403 +
404 + if(base->entries) base->entries->prev = e;
405 + else base->last = e;
406 +
407 + base->entries = e;
408 + base->registered++;
409 + base->wanted = base->registered;
410 +
411 + return base;
412 +}
413 +
414 +static inline int check(struct base *base, const char *s) {
415 + uint32_t hash = simple_hash2(s);
416 +
417 + if(likely(hash == base->last->hash && !strcmp(s, base->last->name))) {
418 + base->last->found = 1;
419 + base->found++;
420 + if(base->last->func) base->last->func(base->last->data1, base->last->data2);
421 + base->last = base->last->next;
422 +
423 + if(!base->last)
424 + base->last = base->entries;
425 +
426 + if(base->found == base->registered)
427 + return 1;
428 +
429 + return 0;
430 + }
431 +
432 + // find it
433 + struct entry *e;
434 + for(e = base->entries; e ; e = e->next)
435 + if(e->hash == hash && !strcmp(e->name, s))
436 + break;
437 +
438 + if(e == base->last) {
439 + printf("ERROR\n");
440 + exit(1);
441 + }
442 +
443 + if(e) {
444 + // found
445 +
446 + // run it
447 + if(e->func) e->func(e->data1, e->data2);
448 +
449 + // unlink it
450 + if(e->next) e->next->prev = e->prev;
451 + if(e->prev) e->prev->next = e->next;
452 +
453 + if(base->entries == e)
454 + base->entries = e->next;
455 + }
456 + else {
457 + // not found
458 +
459 + // create it
460 + e = calloc(1, sizeof(struct entry));
461 + e->name = strdup(s);
462 + e->hash = hash;
463 + }
464 +
465 + // link it here
466 + e->next = base->last;
467 + if(base->last) {
468 + e->prev = base->last->prev;
469 + base->last->prev = e;
470 +
471 + if(base->entries == base->last)
472 + base->entries = e;
473 + }
474 + else
475 + e->prev = NULL;
476 +
477 + if(e->prev)
478 + e->prev->next = e;
479 +
480 + base->last = e->next;
481 + if(!base->last)
482 + base->last = base->entries;
483 +
484 + e->found = 1;
485 + base->found++;
486 +
487 + if(base->found == base->registered)
488 + return 1;
489 +
490 + printf("relinked '%s' after '%s' and before '%s': ", e->name, e->prev?e->prev->name:"NONE", e->next?e->next->name:"NONE");
491 + for(e = base->entries; e ; e = e->next) printf("%s ", e->name);
492 + printf("\n");
493 +
494 + return 0;
495 +}
496 +
497 +static inline void begin(struct base *base) {
498 +
499 + if(unlikely(base->iteration % 60) == 1) {
500 + base->wanted = 0;
501 + struct entry *e;
502 + for(e = base->entries; e ; e = e->next)
503 + if(e->found) base->wanted++;
504 + }
505 +
506 + base->iteration++;
507 + base->last = base->entries;
508 + base->found = 0;
509 +}
510 +
511 +void test6() {
512 +
513 + static struct base *base = NULL;
514 +
515 + if(unlikely(!base)) {
516 + base = entry(base, "cache", NUMBER1, &values6[0], callback);
517 + base = entry(base, "rss", NUMBER2, &values6[1], callback);
518 + base = entry(base, "rss_huge", NUMBER3, &values6[2], callback);
519 + base = entry(base, "mapped_file", NUMBER4, &values6[3], callback);
520 + base = entry(base, "writeback", NUMBER5, &values6[4], callback);
521 + base = entry(base, "dirty", NUMBER6, &values6[5], callback);
522 + base = entry(base, "swap", NUMBER7, &values6[6], callback);
523 + base = entry(base, "pgpgin", NUMBER8, &values6[7], callback);
524 + base = entry(base, "pgpgout", NUMBER9, &values6[8], callback);
525 + base = entry(base, "pgfault", NUMBER10, &values6[9], callback);
526 + base = entry(base, "pgmajfault", NUMBER11, &values6[10], callback);
527 + }
528 +
529 + begin(base);
530 +
531 + int i;
532 + for(i = 0; strings[i] ; i++) {
533 + if(check(base, strings[i]))
534 + break;
535 + }
536 +}
537 +
538 +// ----------------------------------------------------------------------------
539 +
540 +
541 +// ==============
542 +// --- Poor man cycle counting.
543 +static unsigned long tsc;
544 +
545 +static void begin_tsc(void)
546 +{
547 + unsigned long a, d;
548 + asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
549 + tsc = ((unsigned long)d << 32) | (unsigned long)a;
550 +}
551 +
552 +static unsigned long end_tsc(void)
553 +{
554 + unsigned long a, d;
555 + asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
556 + return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
557 +}
558 +// ===============
559 +
560 +static unsigned long long clk;
561 +
562 +static void begin_clock() {
563 + struct timeval tv;
564 + if(unlikely(gettimeofday(&tv, NULL) == -1))
565 + return;
566 + clk = tv.tv_sec * 1000000 + tv.tv_usec;
567 +}
568 +
569 +static unsigned long long end_clock() {
570 + struct timeval tv;
571 + if(unlikely(gettimeofday(&tv, NULL) == -1))
572 + return -1;
573 + return clk = tv.tv_sec * 1000000 + tv.tv_usec - clk;
574 +}
575 +
576 +void main(void)
577 +{
578 + cache_hash = simple_hash("cache");
579 + rss_hash = simple_hash("rss");
580 + rss_huge_hash = simple_hash("rss_huge");
581 + mapped_file_hash = simple_hash("mapped_file");
582 + writeback_hash = simple_hash("writeback");
583 + dirty_hash = simple_hash("dirty");
584 + swap_hash = simple_hash("swap");
585 + pgpgin_hash = simple_hash("pgpgin");
586 + pgpgout_hash = simple_hash("pgpgout");
587 + pgfault_hash = simple_hash("pgfault");
588 + pgmajfault_hash = simple_hash("pgmajfault");
589 + inactive_anon_hash = simple_hash("inactive_anon");
590 + active_anon_hash = simple_hash("active_anon");
591 + inactive_file_hash = simple_hash("inactive_file");
592 + active_file_hash = simple_hash("active_file");
593 + unevictable_hash = simple_hash("unevictable");
594 + hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
595 + total_cache_hash = simple_hash("total_cache");
596 + total_rss_hash = simple_hash("total_rss");
597 + total_rss_huge_hash = simple_hash("total_rss_huge");
598 + total_mapped_file_hash = simple_hash("total_mapped_file");
599 + total_writeback_hash = simple_hash("total_writeback");
600 + total_dirty_hash = simple_hash("total_dirty");
601 + total_swap_hash = simple_hash("total_swap");
602 + total_pgpgin_hash = simple_hash("total_pgpgin");
603 + total_pgpgout_hash = simple_hash("total_pgpgout");
604 + total_pgfault_hash = simple_hash("total_pgfault");
605 + total_pgmajfault_hash = simple_hash("total_pgmajfault");
606 + total_inactive_anon_hash = simple_hash("total_inactive_anon");
607 + total_active_anon_hash = simple_hash("total_active_anon");
608 + total_inactive_file_hash = simple_hash("total_inactive_file");
609 + total_active_file_hash = simple_hash("total_active_file");
610 + total_unevictable_hash = simple_hash("total_unevictable");
611 +
612 + // cache functions
613 + (void)simple_hash2("hello world");
614 + (void)strcmp("1", "2");
615 + (void)strtoull("123", NULL, 0);
616 +
617 + unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0;
618 + unsigned long max = 200000;
619 +
620 + begin_clock();
621 + for(i = 0; i <= max ;i++) test1();
622 + c1 = end_clock();
623 +
624 + begin_clock();
625 + for(i = 0; i <= max ;i++) test2();
626 + c2 = end_clock();
627 +
628 + begin_clock();
629 + for(i = 0; i <= max ;i++) test3();
630 + c3 = end_clock();
631 +
632 + begin_clock();
633 + for(i = 0; i <= max ;i++) test4();
634 + c4 = end_clock();
635 +
636 + begin_clock();
637 + for(i = 0; i <= max ;i++) test5();
638 + c5 = end_clock();
639 +
640 + begin_clock();
641 + for(i = 0; i <= max ;i++) test6();
642 + c6 = end_clock();
643 +
644 + for(i = 0; i < 11 ; i++)
645 + printf("value %lu: %llu %llu %llu %llu %llu %llu\n", i, values1[i], values2[i], values3[i], values4[i], values5[i], values6[i]);
646 +
647 + printf("\n\nRESULTS\n");
648 + printf("test1() in %lu usecs: simple system strcmp().\n"
649 + "test2() in %lu usecs: inline simple_hash() with system strtoull().\n"
650 + "test3() in %lu usecs: statement expression simple_hash(), system strtoull().\n"
651 + "test4() in %lu usecs: inline simple_hash(), if-continue checks.\n"
652 + "test5() in %lu usecs: inline simple_hash(), if-else-if-else-if (netdata default).\n"
653 + "test6() in %lu usecs: adaptive re-sortable array (wow!)\n"
654 + , c1
655 + , c2
656 + , c3
657 + , c4
658 + , c5
659 + , c6
660 + );
661 +
662 +}