diff --git a/.gitignore b/.gitignore
index 04024e6490..df787f5b44 100644
--- a/.gitignore
+++ b/.gitignore
@@ -101,6 +101,7 @@ netdata-updater.sh
 
 # cmake files
 cmake-build-debug/
+cmake-build-release/
 CMakeCache.txt
 CMakeFiles/
 cmake_install.cmake
@@ -130,6 +131,7 @@ tests/profile/benchmark-registry
 tests/profile/test-eval
 tests/profile/benchmark-line-parsing
 tests/profile/benchmark-procfile-parser
+tests/profile/benchmark-value-pairs
 tests/profile/statsd-stress
 oprofile_data/
 vgcore.*
diff --git a/libnetdata/adaptive_resortable_list/README.md b/libnetdata/adaptive_resortable_list/README.md
index b7148b19d4..0ba3ec9b5b 100644
--- a/libnetdata/adaptive_resortable_list/README.md
+++ b/libnetdata/adaptive_resortable_list/README.md
@@ -70,18 +70,22 @@ to extract the same number of expected metrics:
 
 test|code|string comparison|number parsing|duration
 :---:|:---:|:---:|:---:|:---:|
-1|if-else-if-else-if|`strcmp()`|`strtoull()`|4698657 usecs
-2|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`strtoull()`| 872005 usecs
-3|if-else-if-else-if|statement expression `simple_hash()` and `strcmp()`|`strtoull()`|861626 usecs
-4|if-continue|inline `simple_hash()` and `strcmp()`|`strtoull()`|871887 usecs
-5|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`str2ull()`|606541 usecs
-6|ARL|ARL|`strtoull()`|424149 usecs
-7|ARL|ARL|`str2ull()`|199324 usecs
+1|if-else-if-else-if|`strcmp()`|`strtoull()`|4630.337 ms
+2|nested loops|inline `simple_hash()` and `strcmp()`|`strtoull()`|1597.481 ms
+3|nested loops|inline `simple_hash()` and `strcmp()`|`str2ull()`|923.523 ms
+4|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`strtoull()`| 854.574 ms
+5|if-else-if-else-if|statement expression `simple_hash()` and `strcmp()`|`strtoull()`|912.013 ms
+6|if-continue|inline `simple_hash()` and `strcmp()`|`strtoull()`|842.279 ms
+7|if-else-if-else-if|inline `simple_hash()` and `strcmp()`|`str2ull()`|602.837 ms
+8|ARL|ARL|`strtoull()`|350.360 ms
+9|ARL|ARL|`str2ull()`|157.237 ms
 
-So, compared to unoptimized code (test No 1: 4.7sec), before ARL netdata was using test
-No **5** with hashing and a custom `str2ull()` to achieve 607ms.
-The current ARL implementation is test No **7** that needs only 199ms
-(23 times faster vs unoptimized code, 3 times faster vs optimized code).
+Compared to unoptimized code (test No 1: 4.6sec):
+ 
+ - before ARL netdata was using test No **7** with hashing and a custom `str2ull()` to achieve 602ms.
+ - 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).
+
+[Check the source code of this test](../../tests/profile/benchmark-value-pairs.c).
 
 ## Limitations
 
diff --git a/tests/profile/Makefile b/tests/profile/Makefile
index 040219e6fd..5f4e8b5210 100644
--- a/tests/profile/Makefile
+++ b/tests/profile/Makefile
@@ -1,12 +1,53 @@
 # SPDX-License-Identifier: GPL-3.0-or-later
 
-COMMON_CFLAGS=-I ../../src/ -I ../../
-PROFILE_CFLAGS=-O1 -ggdb -Wall -Wextra 
+COMMON_CFLAGS = -I ../../ -DTARGET_OS=1  -Wall -Wextra
+PROFILE_CFLAGS = -O1 -ggdb $(COMMON_CFLAGS)
+PERFORMANCE_CFLAGS = -O2 $(COMMON_CFLAGS)
+
+CFLAGS = $(PERFORMANCE_CFLAGS)
+
+LIBNETDATA_FILES = \
+    ../../libnetdata/popen/popen.o \
+    ../../libnetdata/storage_number/storage_number.o \
+    ../../libnetdata/avl/avl.o \
+    ../../libnetdata/socket/socket.o \
+    ../../libnetdata/os.o \
+    ../../libnetdata/clocks/clocks.o \
+    ../../libnetdata/procfile/procfile.o \
+    ../../libnetdata/statistical/statistical.o \
+    ../../libnetdata/eval/eval.o \
+    ../../libnetdata/threads/threads.o \
+    ../../libnetdata/dictionary/dictionary.o \
+    ../../libnetdata/simple_pattern/simple_pattern.o \
+    ../../libnetdata/url/url.o \
+    ../../libnetdata/config/appconfig.o \
+    ../../libnetdata/libnetdata.o \
+    ../../libnetdata/buffer/buffer.o \
+    ../../libnetdata/adaptive_resortable_list/adaptive_resortable_list.o \
+    ../../libnetdata/locks/locks.o \
+    ../../libnetdata/log/log.o \
+    $(NULL)
+
+COMMON_LDFLAGS = $(LIBNETDATA_FILES) -pthread -lm
+
+all: statsd-stress benchmark-procfile-parser test-eval benchmark-dictionary benchmark-value-pairs
 
 benchmark-procfile-parser: benchmark-procfile-parser.c
-	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
+	gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
+
+benchmark-dictionary: benchmark-dictionary.c
+	gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
+
+benchmark-value-pairs: benchmark-value-pairs.c
+	gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
 
 statsd-stress: statsd-stress.c
-	gcc -O2 -Wall -Wextra -o $@ $^ -pthread
+	gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
+
+test-eval: test-eval.c
+	gcc ${CFLAGS} -o $@ $^ ${COMMON_LDFLAGS}
+
+
+clean:
+	rm -f benchmark-procfile-parser statsd-stress test-eval benchmark-dictionary benchmark-value-pairs
 
-all: statsd-stress benchmark-procfile-parser
diff --git a/tests/profile/benchmark-dictionary.c b/tests/profile/benchmark-dictionary.c
index 18f26737ad..30c098d5db 100644
--- a/tests/profile/benchmark-dictionary.c
+++ b/tests/profile/benchmark-dictionary.c
@@ -7,7 +7,8 @@
  *
  */
 
-#include "common.h"
+#include "config.h"
+#include "libnetdata/libnetdata.h"
 
 struct myvalue {
 	int i;
diff --git a/tests/profile/benchmark-procfile-parser.c b/tests/profile/benchmark-procfile-parser.c
index 4d68f6a44e..991e2dfc80 100644
--- a/tests/profile/benchmark-procfile-parser.c
+++ b/tests/profile/benchmark-procfile-parser.c
@@ -1,7 +1,7 @@
 /* SPDX-License-Identifier: GPL-3.0-or-later */
+
 #include "config.h"
-#include "common.h"
-#include "clocks.h"
+#include "libnetdata/libnetdata.h"
 
 void netdata_cleanup_and_exit(int ret) {
 	exit(ret);
diff --git a/tests/profile/benchmark-strcmp.c b/tests/profile/benchmark-strcmp.c
deleted file mode 100644
index 992c8fd801..0000000000
--- a/tests/profile/benchmark-strcmp.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-#include <stdio.h>
-#include <inttypes.h>
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <sys/time.h>
-
-#define likely(x) __builtin_expect(!!(x), 1)
-#define unlikely(x) __builtin_expect(!!(x), 0)
-
-#define simple_hash(name) ({                                         \
-    register unsigned char *__hash_source = (unsigned char *)(name); \
-    register uint32_t __hash_value = 0x811c9dc5;                     \
-    while (*__hash_source) {                                         \
-        __hash_value *= 16777619;                                    \
-        __hash_value ^= (uint32_t) *__hash_source++;                 \
-    }                                                                \
-    __hash_value;                                                    \
-})
-
-static inline uint32_t simple_hash2(const char *name) {
-    register unsigned char *s = (unsigned char *)name;
-    register uint32_t hval = 0x811c9dc5;
-    while (*s) {
-        hval *= 16777619;
-        hval ^= (uint32_t) *s++;
-    }
-    return hval;
-}
-
-static inline unsigned long long fast_strtoull(const char *s) {
-  register unsigned long long n = 0;
-  register char c;
-  for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
-    n *= 10;
-    n += c - '0';
-    // n = (n << 1) + (n << 3) + (c - '0');
-  }
-  return n;
-}
-
-static uint32_t cache_hash = 0;
-static uint32_t rss_hash = 0;
-static uint32_t rss_huge_hash = 0;
-static uint32_t mapped_file_hash = 0;
-static uint32_t writeback_hash = 0;
-static uint32_t dirty_hash = 0;
-static uint32_t swap_hash = 0;
-static uint32_t pgpgin_hash = 0;
-static uint32_t pgpgout_hash = 0;
-static uint32_t pgfault_hash = 0;
-static uint32_t pgmajfault_hash = 0;
-static uint32_t inactive_anon_hash = 0;
-static uint32_t active_anon_hash = 0;
-static uint32_t inactive_file_hash = 0;
-static uint32_t active_file_hash = 0;
-static uint32_t unevictable_hash = 0;
-static uint32_t hierarchical_memory_limit_hash = 0;
-static uint32_t total_cache_hash = 0;
-static uint32_t total_rss_hash = 0;
-static uint32_t total_rss_huge_hash = 0;
-static uint32_t total_mapped_file_hash = 0;
-static uint32_t total_writeback_hash = 0;
-static uint32_t total_dirty_hash = 0;
-static uint32_t total_swap_hash = 0;
-static uint32_t total_pgpgin_hash = 0;
-static uint32_t total_pgpgout_hash = 0;
-static uint32_t total_pgfault_hash = 0;
-static uint32_t total_pgmajfault_hash = 0;
-static uint32_t total_inactive_anon_hash = 0;
-static uint32_t total_active_anon_hash = 0;
-static uint32_t total_inactive_file_hash = 0;
-static uint32_t total_active_file_hash = 0;
-static uint32_t total_unevictable_hash = 0;
-
-char *strings[] = {
-  "cache",
-  "rss",
-  "rss_huge",
-  "mapped_file",
-  "writeback",
-  "dirty",
-  "swap",
-  "pgpgin",
-  "pgpgout",
-  "pgfault",
-  "pgmajfault",
-  "inactive_anon",
-  "active_anon",
-  "inactive_file",
-  "active_file",
-  "unevictable",
-  "hierarchical_memory_limit",
-  "total_cache",
-  "total_rss",
-  "total_rss_huge",
-  "total_mapped_file",
-  "total_writeback",
-  "total_dirty",
-  "total_swap",
-  "total_pgpgin",
-  "total_pgpgout",
-  "total_pgfault",
-  "total_pgmajfault",
-  "total_inactive_anon",
-  "total_active_anon",
-  "total_inactive_file",
-  "total_active_file",
-  "total_unevictable",
-  NULL
-};
-
-unsigned long long values1[12] = { 0 };
-unsigned long long values2[12] = { 0 };
-unsigned long long values3[12] = { 0 };
-unsigned long long values4[12] = { 0 };
-unsigned long long values5[12] = { 0 };
-unsigned long long values6[12] = { 0 };
-
-#define NUMBER1  "12345678901234"
-#define NUMBER2  "23456789012345"
-#define NUMBER3  "34567890123456"
-#define NUMBER4  "45678901234567"
-#define NUMBER5  "56789012345678"
-#define NUMBER6  "67890123456789"
-#define NUMBER7  "78901234567890"
-#define NUMBER8  "89012345678901"
-#define NUMBER9  "90123456789012"
-#define NUMBER10 "12345678901234"
-#define NUMBER11 "23456789012345"
-
-// simple system strcmp()
-void test1() {
-  int i;
-  for(i = 0; strings[i] ; i++) {
-    char *s = strings[i];
-
-    if(unlikely(!strcmp(s, "cache")))
-      values1[i] = strtoull(NUMBER1, NULL, 10);
-
-    else if(unlikely(!strcmp(s, "rss")))
-      values1[i] = strtoull(NUMBER2, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "rss_huge")))
-      values1[i] = strtoull(NUMBER3, NULL, 10);
-  
-    else if(unlikely(!strcmp(s, "mapped_file")))
-      values1[i] = strtoull(NUMBER4, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "writeback")))
-      values1[i] = strtoull(NUMBER5, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "dirty")))
-      values1[i] = strtoull(NUMBER6, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "swap")))
-      values1[i] = strtoull(NUMBER7, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "pgpgin")))
-      values1[i] = strtoull(NUMBER8, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "pgpgout")))
-      values1[i] = strtoull(NUMBER9, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "pgfault")))
-      values1[i] = strtoull(NUMBER10, NULL, 10);
-    
-    else if(unlikely(!strcmp(s, "pgmajfault")))
-      values1[i] = strtoull(NUMBER11, NULL, 10);
-  }
-}
-
-// inline simple_hash() with system strtoull()
-void test2() {
-  int i;
-  for(i = 0; strings[i] ; i++) {
-    char *s = strings[i];
-    uint32_t hash = simple_hash2(s);
-
-    if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
-      values2[i] = strtoull(NUMBER1, NULL, 10);
-    
-    else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
-      values2[i] = strtoull(NUMBER2, NULL, 10);
-    
-    else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
-      values2[i] = strtoull(NUMBER3, NULL, 10);
-    
-    else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
-      values2[i] = strtoull(NUMBER4, NULL, 10);
-    
-    else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
-      values2[i] = strtoull(NUMBER5, NULL, 10);
-    
-    else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
-      values2[i] = strtoull(NUMBER6, NULL, 10);
-    
-    else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
-      values2[i] = strtoull(NUMBER7, NULL, 10);
-  
-    else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
-      values2[i] = strtoull(NUMBER8, NULL, 10);
-    
-    else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
-      values2[i] = strtoull(NUMBER9, NULL, 10);
-    
-    else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
-      values2[i] = strtoull(NUMBER10, NULL, 10);
-    
-    else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
-      values2[i] = strtoull(NUMBER11, NULL, 10);
-  }
-}
-
-// statement expression simple_hash(), system strtoull()
-void test3() {
-  int i;
-  for(i = 0; strings[i] ; i++) {
-    char *s = strings[i];
-    uint32_t hash = simple_hash(s);
-
-    if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
-      values3[i] = strtoull(NUMBER1, NULL, 10);
-    
-    else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
-      values3[i] = strtoull(NUMBER2, NULL, 10);
-    
-    else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
-      values3[i] = strtoull(NUMBER3, NULL, 10);
-    
-    else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
-      values3[i] = strtoull(NUMBER4, NULL, 10);
-    
-    else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
-      values3[i] = strtoull(NUMBER5, NULL, 10);
-    
-    else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
-      values3[i] = strtoull(NUMBER6, NULL, 10);
-    
-    else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
-      values3[i] = strtoull(NUMBER7, NULL, 10);
-    
-    else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
-      values3[i] = strtoull(NUMBER8, NULL, 10);
-    
-    else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
-      values3[i] = strtoull(NUMBER9, NULL, 10);
-    
-    else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
-      values3[i] = strtoull(NUMBER10, NULL, 10);
-    
-    else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
-      values3[i] = strtoull(NUMBER11, NULL, 10);
-  }
-}
-
-
-// inline simple_hash(), if-continue checks
-void test4() {
-  int i;
-  for(i = 0; strings[i] ; i++) {
-    char *s = strings[i];
-    uint32_t hash = simple_hash2(s);
-
-    if(unlikely(hash == cache_hash && !strcmp(s, "cache"))) {
-      values4[i] = strtoull(NUMBER1, NULL, 0);
-      continue;
-    }
-
-    if(unlikely(hash == rss_hash && !strcmp(s, "rss"))) {
-      values4[i] = strtoull(NUMBER2, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge"))) {
-      values4[i] = strtoull(NUMBER3, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file"))) {
-      values4[i] = strtoull(NUMBER4, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == writeback_hash && !strcmp(s, "writeback"))) {
-      values4[i] = strtoull(NUMBER5, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == dirty_hash && !strcmp(s, "dirty"))) {
-      values4[i] = strtoull(NUMBER6, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == swap_hash && !strcmp(s, "swap"))) {
-      values4[i] = strtoull(NUMBER7, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin"))) {
-      values4[i] = strtoull(NUMBER8, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout"))) {
-      values4[i] = strtoull(NUMBER9, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault"))) {
-      values4[i] = strtoull(NUMBER10, NULL, 0);
-      continue;
-    }
-    
-    if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))) {
-      values4[i] = strtoull(NUMBER11, NULL, 0);
-      continue;
-    }
-  }
-}
-
-// inline simple_hash(), if-else-if-else-if (netdata default)
-void test5() {
-  int i;
-  for(i = 0; strings[i] ; i++) {
-    char *s = strings[i];
-    uint32_t hash = simple_hash2(s);
-
-    if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
-      values5[i] = fast_strtoull(NUMBER1);
-    
-    else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
-      values5[i] = fast_strtoull(NUMBER2);
-    
-    else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
-      values5[i] = fast_strtoull(NUMBER3);
-    
-    else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
-      values5[i] = fast_strtoull(NUMBER4);
-    
-    else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
-      values5[i] = fast_strtoull(NUMBER5);
-    
-    else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
-      values5[i] = fast_strtoull(NUMBER6);
-    
-    else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
-      values5[i] = fast_strtoull(NUMBER7);
-  
-    else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
-      values5[i] = fast_strtoull(NUMBER8);
-    
-    else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
-      values5[i] = fast_strtoull(NUMBER9);
-    
-    else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
-      values5[i] = fast_strtoull(NUMBER10);
-    
-    else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
-      values5[i] = fast_strtoull(NUMBER11);
-  }
-}
-
-// ----------------------------------------------------------------------------
-
-struct entry {
-  char *name;
-  uint32_t hash;
-  int found;
-  void (*func)(void *data1, void *data2);
-  void *data1;
-  void *data2;
-  struct entry *prev, *next;
-};
-
-struct base {
-  int iteration;
-  int registered;
-  int wanted;
-  int found;
-  struct entry *entries, *last;
-};
-
-static inline void callback(void *data1, void *data2) {
-  char *string = data1;
-  unsigned long long *value = data2;
-  *value = fast_strtoull(string);
-}
-
-
-static inline struct base *entry(struct base *base, const char *name, void *data1, void *data2, void (*func)(void *, void *)) {
-  if(!base)
-    base = calloc(1, sizeof(struct base));
-
-  struct entry *e = malloc(sizeof(struct entry));
-  e->name = strdup(name);
-  e->hash = simple_hash2(e->name);
-  e->data1 = data1;
-  e->data2 = data2;
-  e->func = func;
-  e->prev = NULL;
-  e->next = base->entries;
-
-  if(base->entries) base->entries->prev = e;
-  else base->last = e;
-
-  base->entries = e;
-  base->registered++;
-  base->wanted = base->registered;
-
-  return base;
-}
-
-static inline int check(struct base *base, const char *s) {
-  uint32_t hash = simple_hash2(s);
-
-  if(likely(hash == base->last->hash && !strcmp(s, base->last->name))) {
-    base->last->found = 1;
-    base->found++;
-    if(base->last->func) base->last->func(base->last->data1, base->last->data2);
-    base->last = base->last->next;
-
-    if(!base->last)
-      base->last = base->entries;
-
-    if(base->found == base->registered)
-      return 1;
-
-    return 0;
-  }
-
-  // find it
-  struct entry *e;
-  for(e = base->entries; e ; e = e->next)
-    if(e->hash == hash && !strcmp(e->name, s))
-      break;
-
-  if(e == base->last) {
-    printf("ERROR\n");
-    exit(1);
-  }
-
-  if(e) {
-    // found
-
-    // run it
-    if(e->func) e->func(e->data1, e->data2);
-
-    // unlink it
-    if(e->next) e->next->prev = e->prev;
-    if(e->prev) e->prev->next = e->next;
-
-    if(base->entries == e)
-      base->entries = e->next;
-  }
-  else {
-    // not found
-
-    // create it
-    e = calloc(1, sizeof(struct entry));
-    e->name = strdup(s);
-    e->hash = hash;
-  }
-
-  // link it here
-  e->next = base->last;
-  if(base->last) {
-    e->prev = base->last->prev;
-    base->last->prev = e;
-
-    if(base->entries == base->last)
-      base->entries = e;
-  }
-  else
-    e->prev = NULL;
-
-  if(e->prev)
-    e->prev->next = e;
-
-  base->last = e->next;
-  if(!base->last)
-    base->last = base->entries;
-
-  e->found = 1;
-  base->found++;
-
-  if(base->found == base->registered)
-    return 1;
-
-  printf("relinked '%s' after '%s' and before '%s': ", e->name, e->prev?e->prev->name:"NONE", e->next?e->next->name:"NONE");
-  for(e = base->entries; e ; e = e->next) printf("%s ", e->name);
-  printf("\n");
-
-  return 0;
-}
-
-static inline void begin(struct base *base) {
-
-  if(unlikely(base->iteration % 60) == 1) {
-    base->wanted = 0;
-    struct entry *e;
-    for(e = base->entries; e ; e = e->next)
-      if(e->found) base->wanted++;
-  }
-
-  base->iteration++;
-  base->last = base->entries;
-  base->found = 0;
-}
-
-void test6() {
-
-  static struct base *base = NULL;
-
-  if(unlikely(!base)) {
-    base = entry(base, "cache", NUMBER1, &values6[0], callback);
-    base = entry(base, "rss", NUMBER2, &values6[1], callback);
-    base = entry(base, "rss_huge", NUMBER3, &values6[2], callback);
-    base = entry(base, "mapped_file", NUMBER4, &values6[3], callback);
-    base = entry(base, "writeback", NUMBER5, &values6[4], callback);
-    base = entry(base, "dirty", NUMBER6, &values6[5], callback);
-    base = entry(base, "swap", NUMBER7, &values6[6], callback);
-    base = entry(base, "pgpgin", NUMBER8, &values6[7], callback);
-    base = entry(base, "pgpgout", NUMBER9, &values6[8], callback);
-    base = entry(base, "pgfault", NUMBER10, &values6[9], callback);
-    base = entry(base, "pgmajfault", NUMBER11, &values6[10], callback);
-  }
-
-  begin(base);
-
-  int i;
-  for(i = 0; strings[i] ; i++) {
-    if(check(base, strings[i]))
-      break;
-  }
-}
-
-// ----------------------------------------------------------------------------
-
-
-// ==============
-// --- Poor man cycle counting.
-static unsigned long tsc;
-
-static void begin_tsc(void)
-{
-  unsigned long a, d;
-  asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
-  tsc = ((unsigned long)d << 32) | (unsigned long)a;
-}
-
-static unsigned long end_tsc(void)
-{
-  unsigned long a, d;
-  asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
-  return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
-}
-// ===============
-
-static unsigned long long clk;
-
-static void begin_clock() {
-    struct timeval tv;
-    if(unlikely(gettimeofday(&tv, NULL) == -1))
-        return;
-    clk = tv.tv_sec  * 1000000 + tv.tv_usec;
-}
-
-static unsigned long long end_clock() {
-    struct timeval tv;
-    if(unlikely(gettimeofday(&tv, NULL) == -1))
-        return -1;
-    return clk = tv.tv_sec  * 1000000 + tv.tv_usec - clk;
-}
-
-void main(void)
-{
-    cache_hash = simple_hash("cache");
-    rss_hash = simple_hash("rss");
-    rss_huge_hash = simple_hash("rss_huge");
-    mapped_file_hash = simple_hash("mapped_file");
-    writeback_hash = simple_hash("writeback");
-    dirty_hash = simple_hash("dirty");
-    swap_hash = simple_hash("swap");
-    pgpgin_hash = simple_hash("pgpgin");
-    pgpgout_hash = simple_hash("pgpgout");
-    pgfault_hash = simple_hash("pgfault");
-    pgmajfault_hash = simple_hash("pgmajfault");
-    inactive_anon_hash = simple_hash("inactive_anon");
-    active_anon_hash = simple_hash("active_anon");
-    inactive_file_hash = simple_hash("inactive_file");
-    active_file_hash = simple_hash("active_file");
-    unevictable_hash = simple_hash("unevictable");
-    hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
-    total_cache_hash = simple_hash("total_cache");
-    total_rss_hash = simple_hash("total_rss");
-    total_rss_huge_hash = simple_hash("total_rss_huge");
-    total_mapped_file_hash = simple_hash("total_mapped_file");
-    total_writeback_hash = simple_hash("total_writeback");
-    total_dirty_hash = simple_hash("total_dirty");
-    total_swap_hash = simple_hash("total_swap");
-    total_pgpgin_hash = simple_hash("total_pgpgin");
-    total_pgpgout_hash = simple_hash("total_pgpgout");
-    total_pgfault_hash = simple_hash("total_pgfault");
-    total_pgmajfault_hash = simple_hash("total_pgmajfault");
-    total_inactive_anon_hash = simple_hash("total_inactive_anon");
-    total_active_anon_hash = simple_hash("total_active_anon");
-    total_inactive_file_hash = simple_hash("total_inactive_file");
-    total_active_file_hash = simple_hash("total_active_file");
-    total_unevictable_hash = simple_hash("total_unevictable");
-
-    // cache functions
-    (void)simple_hash2("hello world");
-    (void)strcmp("1", "2");
-    (void)strtoull("123", NULL, 0);
-
-  unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0;
-  unsigned long max = 200000;
-
-  begin_clock();
-  for(i = 0; i <= max ;i++) test1();
-  c1 = end_clock();
-
-  begin_clock();
-  for(i = 0; i <= max ;i++) test2();
-  c2 = end_clock();
-    
-  begin_clock();
-  for(i = 0; i <= max ;i++) test3();
-  c3 = end_clock();
-
-  begin_clock();
-  for(i = 0; i <= max ;i++) test4();
-  c4 = end_clock();
-
-  begin_clock();
-  for(i = 0; i <= max ;i++) test5();
-  c5 = end_clock();
-
-  begin_clock();
-  for(i = 0; i <= max ;i++) test6();
-  c6 = end_clock();
-
-  for(i = 0; i < 11 ; i++)
-    printf("value %lu: %llu %llu %llu %llu %llu %llu\n", i, values1[i], values2[i], values3[i], values4[i], values5[i], values6[i]);
-  
-  printf("\n\nRESULTS\n");
-  printf("test1() in %lu usecs: simple system strcmp().\n"
-         "test2() in %lu usecs: inline simple_hash() with system strtoull().\n"
-         "test3() in %lu usecs: statement expression simple_hash(), system strtoull().\n"
-         "test4() in %lu usecs: inline simple_hash(), if-continue checks.\n"
-         "test5() in %lu usecs: inline simple_hash(), if-else-if-else-if (netdata default).\n"
-         "test6() in %lu usecs: adaptive re-sortable array (wow!)\n"
-         , c1
-         , c2
-         , c3
-         , c4
-         , c5
-         , c6
-         );
-
-}
diff --git a/tests/profile/benchmark-value-pairs.c b/tests/profile/benchmark-value-pairs.c
new file mode 100644
index 0000000000..ae4f53c3a7
--- /dev/null
+++ b/tests/profile/benchmark-value-pairs.c
@@ -0,0 +1,623 @@
+/* SPDX-License-Identifier: GPL-3.0-or-later */
+
+#include "config.h"
+#include "libnetdata/libnetdata.h"
+
+#ifdef simple_hash
+#undef simple_hash
+#endif
+
+void netdata_cleanup_and_exit(int ret) {
+    exit(ret);
+}
+
+#define simple_hash(name) ({                                         \
+    register unsigned char *__hash_source = (unsigned char *)(name); \
+    register uint32_t __hash_value = 0x811c9dc5;                     \
+    while (*__hash_source) {                                         \
+        __hash_value *= 16777619;                                    \
+        __hash_value ^= (uint32_t) *__hash_source++;                 \
+    }                                                                \
+    __hash_value;                                                    \
+})
+
+static inline uint32_t simple_hash2(const char *name) {
+    register unsigned char *s = (unsigned char *)name;
+    register uint32_t hval = 0x811c9dc5;
+    while (*s) {
+        hval *= 16777619;
+        hval ^= (uint32_t) *s++;
+    }
+    return hval;
+}
+
+static inline unsigned long long fast_strtoull(const char *s) {
+  register unsigned long long n = 0;
+  register char c;
+  for(c = *s; c >= '0' && c <= '9' ; c = *(++s)) {
+    n *= 10;
+    n += c - '0';
+    // n = (n << 1) + (n << 3) + (c - '0');
+  }
+  return n;
+}
+
+static uint32_t cache_hash = 0;
+static uint32_t rss_hash = 0;
+static uint32_t rss_huge_hash = 0;
+static uint32_t mapped_file_hash = 0;
+static uint32_t writeback_hash = 0;
+static uint32_t dirty_hash = 0;
+static uint32_t swap_hash = 0;
+static uint32_t pgpgin_hash = 0;
+static uint32_t pgpgout_hash = 0;
+static uint32_t pgfault_hash = 0;
+static uint32_t pgmajfault_hash = 0;
+static uint32_t inactive_anon_hash = 0;
+static uint32_t active_anon_hash = 0;
+static uint32_t inactive_file_hash = 0;
+static uint32_t active_file_hash = 0;
+static uint32_t unevictable_hash = 0;
+static uint32_t hierarchical_memory_limit_hash = 0;
+static uint32_t total_cache_hash = 0;
+static uint32_t total_rss_hash = 0;
+static uint32_t total_rss_huge_hash = 0;
+static uint32_t total_mapped_file_hash = 0;
+static uint32_t total_writeback_hash = 0;
+static uint32_t total_dirty_hash = 0;
+static uint32_t total_swap_hash = 0;
+static uint32_t total_pgpgin_hash = 0;
+static uint32_t total_pgpgout_hash = 0;
+static uint32_t total_pgfault_hash = 0;
+static uint32_t total_pgmajfault_hash = 0;
+static uint32_t total_inactive_anon_hash = 0;
+static uint32_t total_active_anon_hash = 0;
+static uint32_t total_inactive_file_hash = 0;
+static uint32_t total_active_file_hash = 0;
+static uint32_t total_unevictable_hash = 0;
+
+unsigned long long values1[50] = { 0 };
+unsigned long long values2[50] = { 0 };
+unsigned long long values3[50] = { 0 };
+unsigned long long values4[50] = { 0 };
+unsigned long long values5[50] = { 0 };
+unsigned long long values6[50] = { 0 };
+unsigned long long values7[50] = { 0 };
+unsigned long long values8[50] = { 0 };
+unsigned long long values9[50] = { 0 };
+
+struct pair {
+    const char *name;
+    const char *value;
+    uint32_t hash;
+    unsigned long long *collected8;
+    unsigned long long *collected9;
+} pairs[] = {
+        { "cache",                      "12345678901234", 0, &values8[0]  ,&values9[0] },
+        { "rss",                        "23456789012345", 0, &values8[1]  ,&values9[1] },
+        { "rss_huge",                   "34567890123456", 0, &values8[2]  ,&values9[2] },
+        { "mapped_file",                "45678901234567", 0, &values8[3]  ,&values9[3] },
+        { "writeback",                  "56789012345678", 0, &values8[4]  ,&values9[4] },
+        { "dirty",                      "67890123456789", 0, &values8[5]  ,&values9[5] },
+        { "swap",                       "78901234567890", 0, &values8[6]  ,&values9[6] },
+        { "pgpgin",                     "89012345678901", 0, &values8[7]  ,&values9[7] },
+        { "pgpgout",                    "90123456789012", 0, &values8[8]  ,&values9[8] },
+        { "pgfault",                    "10345678901234", 0, &values8[9]  ,&values9[9] },
+        { "pgmajfault",                 "11456789012345", 0, &values8[10] ,&values9[10] },
+        { "inactive_anon",              "12000000000000", 0, &values8[11] ,&values9[11] },
+        { "active_anon",                "13345678901234", 0, &values8[12] ,&values9[12] },
+        { "inactive_file",              "14345678901234", 0, &values8[13] ,&values9[13] },
+        { "active_file",                "15345678901234", 0, &values8[14] ,&values9[14] },
+        { "unevictable",                "16345678901234", 0, &values8[15] ,&values9[15] },
+        { "hierarchical_memory_limit",  "17345678901234", 0, &values8[16] ,&values9[16] },
+        { "total_cache",                "18345678901234", 0, &values8[17] ,&values9[17] },
+        { "total_rss",                  "19345678901234", 0, &values8[18] ,&values9[18] },
+        { "total_rss_huge",             "20345678901234", 0, &values8[19] ,&values9[19] },
+        { "total_mapped_file",          "21345678901234", 0, &values8[20] ,&values9[20] },
+        { "total_writeback",            "22345678901234", 0, &values8[21] ,&values9[21] },
+        { "total_dirty",                "23000000000000", 0, &values8[22] ,&values9[22] },
+        { "total_swap",                 "24345678901234", 0, &values8[23] ,&values9[23] },
+        { "total_pgpgin",               "25345678901234", 0, &values8[24] ,&values9[24] },
+        { "total_pgpgout",              "26345678901234", 0, &values8[25] ,&values9[25] },
+        { "total_pgfault",              "27345678901234", 0, &values8[26] ,&values9[26] },
+        { "total_pgmajfault",           "28345678901234", 0, &values8[27] ,&values9[27] },
+        { "total_inactive_anon",        "29345678901234", 0, &values8[28] ,&values9[28] },
+        { "total_active_anon",          "30345678901234", 0, &values8[29] ,&values9[29] },
+        { "total_inactive_file",        "31345678901234", 0, &values8[30] ,&values9[30] },
+        { "total_active_file",          "32345678901234", 0, &values8[31] ,&values9[31] },
+        { "total_unevictable",          "33345678901234", 0, &values8[32] ,&values9[32] },
+        { NULL,                         NULL            , 0, NULL         ,NULL         }
+};
+
+// simple system strcmp()
+void test1() {
+  int i;
+  for(i = 0; pairs[i].name ; i++) {
+    const char *s = pairs[i].name;
+    const char *v = pairs[i].value;
+
+    if(unlikely(!strcmp(s, "cache")))
+      values1[i] = strtoull(v, NULL, 10);
+
+    else if(unlikely(!strcmp(s, "rss")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "rss_huge")))
+      values1[i] = strtoull(v, NULL, 10);
+  
+    else if(unlikely(!strcmp(s, "mapped_file")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "writeback")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "dirty")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "swap")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "pgpgin")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "pgpgout")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "pgfault")))
+      values1[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(!strcmp(s, "pgmajfault")))
+      values1[i] = strtoull(v, NULL, 10);
+  }
+}
+
+// inline simple_hash() with system strtoull()
+void test2() {
+    int i;
+    for(i = 0; pairs[i].name ; i++) {
+        const char *s = pairs[i].name;
+        const char *v = pairs[i].value;
+
+    uint32_t hash = simple_hash2(s);
+
+    if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
+      values2[i] = strtoull(v, NULL, 10);
+  
+    else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
+      values2[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
+      values2[i] = strtoull(v, NULL, 10);
+  }
+}
+
+// statement expression simple_hash(), system strtoull()
+void test3() {
+    int i;
+    for(i = 0; pairs[i].name ; i++) {
+        const char *s = pairs[i].name;
+        const char *v = pairs[i].value;
+
+    uint32_t hash = simple_hash(s);
+
+    if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
+      values3[i] = strtoull(v, NULL, 10);
+    
+    else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
+      values3[i] = strtoull(v, NULL, 10);
+  }
+}
+
+
+// inline simple_hash(), if-continue checks
+void test4() {
+    int i;
+    for(i = 0; pairs[i].name ; i++) {
+        const char *s = pairs[i].name;
+        const char *v = pairs[i].value;
+
+    uint32_t hash = simple_hash2(s);
+
+    if(unlikely(hash == cache_hash && !strcmp(s, "cache"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+
+    if(unlikely(hash == rss_hash && !strcmp(s, "rss"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == writeback_hash && !strcmp(s, "writeback"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == dirty_hash && !strcmp(s, "dirty"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == swap_hash && !strcmp(s, "swap"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+    
+    if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault"))) {
+      values4[i] = strtoull(v, NULL, 0);
+      continue;
+    }
+  }
+}
+
+// inline simple_hash(), if-else-if-else-if (netdata default)
+void test5() {
+    int i;
+    for(i = 0; pairs[i].name ; i++) {
+        const char *s = pairs[i].name;
+        const char *v = pairs[i].value;
+
+    uint32_t hash = simple_hash2(s);
+
+    if(unlikely(hash == cache_hash && !strcmp(s, "cache")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == rss_hash && !strcmp(s, "rss")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == rss_huge_hash && !strcmp(s, "rss_huge")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == mapped_file_hash && !strcmp(s, "mapped_file")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == writeback_hash && !strcmp(s, "writeback")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == dirty_hash && !strcmp(s, "dirty")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == swap_hash && !strcmp(s, "swap")))
+      values5[i] = fast_strtoull(v);
+  
+    else if(unlikely(hash == pgpgin_hash && !strcmp(s, "pgpgin")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == pgpgout_hash && !strcmp(s, "pgpgout")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == pgfault_hash && !strcmp(s, "pgfault")))
+      values5[i] = fast_strtoull(v);
+    
+    else if(unlikely(hash == pgmajfault_hash && !strcmp(s, "pgmajfault")))
+      values5[i] = fast_strtoull(v);
+  }
+}
+
+// ----------------------------------------------------------------------------
+
+void arl_strtoull(const char *name, uint32_t hash, const char *value, void *dst) {
+    (void)name;
+    (void)hash;
+
+    register unsigned long long *d = dst;
+    *d = strtoull(value, NULL, 10);
+    // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, *d);
+}
+
+void test6() {
+    static ARL_BASE *base = NULL;
+
+    if(unlikely(!base)) {
+        base = arl_create("test6", arl_strtoull, 60);
+        arl_expect_custom(base, "cache",       NULL, &values6[0]);
+        arl_expect_custom(base, "rss",         NULL, &values6[1]);
+        arl_expect_custom(base, "rss_huge",    NULL, &values6[2]);
+        arl_expect_custom(base, "mapped_file", NULL, &values6[3]);
+        arl_expect_custom(base, "writeback",   NULL, &values6[4]);
+        arl_expect_custom(base, "dirty",       NULL, &values6[5]);
+        arl_expect_custom(base, "swap",        NULL, &values6[6]);
+        arl_expect_custom(base, "pgpgin",      NULL, &values6[7]);
+        arl_expect_custom(base, "pgpgout",     NULL, &values6[8]);
+        arl_expect_custom(base, "pgfault",     NULL, &values6[9]);
+        arl_expect_custom(base, "pgmajfault",  NULL, &values6[10]);
+    }
+
+    arl_begin(base);
+
+    int i;
+    for(i = 0; pairs[i].name ; i++)
+        if(arl_check(base, pairs[i].name, pairs[i].value)) break;
+}
+
+void arl_str2ull(const char *name, uint32_t hash, const char *value, void *dst) {
+    (void)name;
+    (void)hash;
+
+    register unsigned long long *d = dst;
+    *d = str2ull(value);
+    // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, *d);
+}
+
+void test7() {
+    static ARL_BASE *base = NULL;
+
+    if(unlikely(!base)) {
+        base = arl_create("test7", arl_str2ull, 60);
+        arl_expect_custom(base, "cache",       NULL, &values7[0]);
+        arl_expect_custom(base, "rss",         NULL, &values7[1]);
+        arl_expect_custom(base, "rss_huge",    NULL, &values7[2]);
+        arl_expect_custom(base, "mapped_file", NULL, &values7[3]);
+        arl_expect_custom(base, "writeback",   NULL, &values7[4]);
+        arl_expect_custom(base, "dirty",       NULL, &values7[5]);
+        arl_expect_custom(base, "swap",        NULL, &values7[6]);
+        arl_expect_custom(base, "pgpgin",      NULL, &values7[7]);
+        arl_expect_custom(base, "pgpgout",     NULL, &values7[8]);
+        arl_expect_custom(base, "pgfault",     NULL, &values7[9]);
+        arl_expect_custom(base, "pgmajfault",  NULL, &values7[10]);
+    }
+
+    arl_begin(base);
+
+    int i;
+    for(i = 0; pairs[i].name ; i++)
+        if(arl_check(base, pairs[i].name, pairs[i].value)) break;
+}
+
+void test8() {
+    int i;
+    for(i = 0; pairs[i].name; i++) {
+        uint32_t hash = simple_hash(pairs[i].name);
+
+        int j;
+        for(j = 0; pairs[j].name; j++) {
+            if(hash == pairs[j].hash && !strcmp(pairs[i].name, pairs[j].name)) {
+                *pairs[j].collected8 = strtoull(pairs[i].value, NULL, 10);
+                break;
+            }
+        }
+    }
+}
+
+void test9() {
+    int i;
+    for(i = 0; pairs[i].name; i++) {
+        uint32_t hash = simple_hash(pairs[i].name);
+
+        int j;
+        for(j = 0; pairs[j].name; j++) {
+            if(hash == pairs[j].hash && !strcmp(pairs[i].name, pairs[j].name)) {
+                *pairs[j].collected9 = str2ull(pairs[i].value);
+                break;
+            }
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+/*
+// ==============
+// --- Poor man cycle counting.
+static unsigned long tsc;
+
+static void begin_tsc(void)
+{
+  unsigned long a, d;
+  asm volatile ("cpuid\nrdtsc" : "=a" (a), "=d" (d) : "0" (0) : "ebx", "ecx");
+  tsc = ((unsigned long)d << 32) | (unsigned long)a;
+}
+
+static unsigned long end_tsc(void)
+{
+  unsigned long a, d;
+  asm volatile ("rdtscp" : "=a" (a), "=d" (d) : : "ecx");
+  return (((unsigned long)d << 32) | (unsigned long)a) - tsc;
+}
+// ===============
+*/
+
+static unsigned long long clk;
+
+static void begin_clock() {
+    struct timeval tv;
+    if(unlikely(gettimeofday(&tv, NULL) == -1))
+        return;
+    clk = tv.tv_sec  * 1000000 + tv.tv_usec;
+}
+
+static unsigned long long end_clock() {
+    struct timeval tv;
+    if(unlikely(gettimeofday(&tv, NULL) == -1))
+        return -1;
+    return clk = tv.tv_sec  * 1000000 + tv.tv_usec - clk;
+}
+
+int main(void)
+{
+    {
+        int i;
+        for(i = 0; pairs[i].name; i++)
+            pairs[i].hash = simple_hash(pairs[i].name);
+    }
+
+    cache_hash = simple_hash("cache");
+    rss_hash = simple_hash("rss");
+    rss_huge_hash = simple_hash("rss_huge");
+    mapped_file_hash = simple_hash("mapped_file");
+    writeback_hash = simple_hash("writeback");
+    dirty_hash = simple_hash("dirty");
+    swap_hash = simple_hash("swap");
+    pgpgin_hash = simple_hash("pgpgin");
+    pgpgout_hash = simple_hash("pgpgout");
+    pgfault_hash = simple_hash("pgfault");
+    pgmajfault_hash = simple_hash("pgmajfault");
+    inactive_anon_hash = simple_hash("inactive_anon");
+    active_anon_hash = simple_hash("active_anon");
+    inactive_file_hash = simple_hash("inactive_file");
+    active_file_hash = simple_hash("active_file");
+    unevictable_hash = simple_hash("unevictable");
+    hierarchical_memory_limit_hash = simple_hash("hierarchical_memory_limit");
+    total_cache_hash = simple_hash("total_cache");
+    total_rss_hash = simple_hash("total_rss");
+    total_rss_huge_hash = simple_hash("total_rss_huge");
+    total_mapped_file_hash = simple_hash("total_mapped_file");
+    total_writeback_hash = simple_hash("total_writeback");
+    total_dirty_hash = simple_hash("total_dirty");
+    total_swap_hash = simple_hash("total_swap");
+    total_pgpgin_hash = simple_hash("total_pgpgin");
+    total_pgpgout_hash = simple_hash("total_pgpgout");
+    total_pgfault_hash = simple_hash("total_pgfault");
+    total_pgmajfault_hash = simple_hash("total_pgmajfault");
+    total_inactive_anon_hash = simple_hash("total_inactive_anon");
+    total_active_anon_hash = simple_hash("total_active_anon");
+    total_inactive_file_hash = simple_hash("total_inactive_file");
+    total_active_file_hash = simple_hash("total_active_file");
+    total_unevictable_hash = simple_hash("total_unevictable");
+
+    // cache functions
+    (void)simple_hash2("hello world");
+    (void)strcmp("1", "2");
+    (void)strtoull("123", NULL, 0);
+
+  unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0, c7 = 0, c8 = 0, c9 = 0;
+  unsigned long max = 1000000;
+
+  begin_clock();
+  for(i = 0; i <= max ;i++) test1();
+  c1 = end_clock();
+
+  begin_clock();
+  for(i = 0; i <= max ;i++) test2();
+  c2 = end_clock();
+    
+  begin_clock();
+  for(i = 0; i <= max ;i++) test3();
+  c3 = end_clock();
+
+  begin_clock();
+  for(i = 0; i <= max ;i++) test4();
+  c4 = end_clock();
+
+  begin_clock();
+  for(i = 0; i <= max ;i++) test5();
+  c5 = end_clock();
+
+    begin_clock();
+    for(i = 0; i <= max ;i++) test6();
+    c6 = end_clock();
+
+    begin_clock();
+    for(i = 0; i <= max ;i++) test7();
+    c7 = end_clock();
+
+    begin_clock();
+    for(i = 0; i <= max ;i++) test8();
+    c8 = end_clock();
+
+    begin_clock();
+    for(i = 0; i <= max ;i++) test9();
+    c9 = end_clock();
+
+    for(i = 0; i < 11 ; i++)
+        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]);
+  
+  printf("\n\nRESULTS\n");
+  printf("test1() [1] in %lu usecs: simple system strcmp().\n"
+         "test2() [4] in %lu usecs: inline simple_hash() with system strtoull().\n"
+         "test3() [5] in %lu usecs: statement expression simple_hash(), system strtoull().\n"
+         "test4() [6] in %lu usecs: inline simple_hash(), if-continue checks.\n"
+         "test5() [7] in %lu usecs: inline simple_hash(), if-else-if-else-if (netdata default prior to ARL).\n"
+         "test6() [8] in %lu usecs: adaptive re-sortable array with strtoull() (wow!)\n"
+         "test7() [9] in %lu usecs: adaptive re-sortable array with str2ull() (wow!)\n"
+         "test8() [2] in %lu usecs: nested loop with strtoull()\n"
+         "test9() [3] in %lu usecs: nested loop with str2ull()\n"
+         , c1
+         , c2
+         , c3
+         , c4
+         , c5
+         , c6
+         , c7
+         , c8
+         , c9
+         );
+
+  return 0;
+}
diff --git a/tests/profile/test-eval.c b/tests/profile/test-eval.c
index d777c5d221..144381cf08 100644
--- a/tests/profile/test-eval.c
+++ b/tests/profile/test-eval.c
@@ -8,8 +8,8 @@
  */
 
 #include "config.h"
-#include "common.h"
-#include "clocks.h"
+#include "libnetdata/libnetdata.h"
+#include "database/rrdcalc.h"
 
 void netdata_cleanup_and_exit(int ret) { exit(ret); }