703 lines
20 KiB
C
703 lines
20 KiB
C
/* 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 void callback_system_strtoull(void *data1, void *data2) {
|
|
char *string = data1;
|
|
unsigned long long *value = data2;
|
|
*value = strtoull(string, NULL, 10);
|
|
}
|
|
|
|
|
|
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(!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_system_strtoull);
|
|
base = entry(base, "rss", NUMBER2, &values6[1], callback_system_strtoull);
|
|
base = entry(base, "rss_huge", NUMBER3, &values6[2], callback_system_strtoull);
|
|
base = entry(base, "mapped_file", NUMBER4, &values6[3], callback_system_strtoull);
|
|
base = entry(base, "writeback", NUMBER5, &values6[4], callback_system_strtoull);
|
|
base = entry(base, "dirty", NUMBER6, &values6[5], callback_system_strtoull);
|
|
base = entry(base, "swap", NUMBER7, &values6[6], callback_system_strtoull);
|
|
base = entry(base, "pgpgin", NUMBER8, &values6[7], callback_system_strtoull);
|
|
base = entry(base, "pgpgout", NUMBER9, &values6[8], callback_system_strtoull);
|
|
base = entry(base, "pgfault", NUMBER10, &values6[9], callback_system_strtoull);
|
|
base = entry(base, "pgmajfault", NUMBER11, &values6[10], callback_system_strtoull);
|
|
}
|
|
|
|
begin(base);
|
|
|
|
int i;
|
|
for(i = 0; strings[i] ; i++) {
|
|
if(check(base, strings[i]))
|
|
break;
|
|
}
|
|
}
|
|
|
|
void test7() {
|
|
|
|
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");
|
|
|
|
unsigned long i, c1 = 0, c2 = 0, c3 = 0, c4 = 0, c5 = 0, c6 = 0, c7;
|
|
unsigned long max = 1000000;
|
|
|
|
// let the processor get up to speed
|
|
begin_clock();
|
|
for(i = 0; i <= max ;i++) test1();
|
|
c1 = end_clock();
|
|
|
|
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();
|
|
|
|
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: if-else-if-else-if, simple strcmp() with system strtoull().\n"
|
|
"test2() in %lu usecs: inline simple_hash() if-else-if-else-if, 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, system strtoull().\n"
|
|
"test5() in %lu usecs: inline simple_hash(), if-else-if-else-if, custom strtoull() (netdata default prior to ARL).\n"
|
|
"test6() in %lu usecs: adaptive re-sortable list, system strtoull() (wow!)\n"
|
|
"test7() in %lu usecs: adaptive re-sortable list, custom strtoull() (wow!)\n"
|
|
, c1
|
|
, c2
|
|
, c3
|
|
, c4
|
|
, c5
|
|
, c6
|
|
, c7
|
|
);
|
|
|
|
}
|