]> arthur.barton.de Git - netdata.git/commitdiff
lower dictionary memory requirements by keeping pointers to optional features
authorCosta Tsaousis <costa@tsaousis.gr>
Thu, 2 Jun 2016 11:21:58 +0000 (14:21 +0300)
committerCosta Tsaousis <costa@tsaousis.gr>
Thu, 2 Jun 2016 11:21:58 +0000 (14:21 +0300)
profile/benchmark-dictionary.c
src/dictionary.c
src/dictionary.h

index 61f0d02ddadc7cab1fc76e631dc3ee9b517ea430..6e524797551d24011dcf2380ebbe54a53d50dd6c 100644 (file)
@@ -22,19 +22,20 @@ struct myvalue {
 int main(int argc, char **argv) {
        if(argc || argv) {;}
 
-       DICTIONARY *dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
+//     DICTIONARY *dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED|DICTIONARY_FLAG_WITH_STATISTICS);
+       DICTIONARY *dict = dictionary_create(DICTIONARY_FLAG_WITH_STATISTICS);
        if(!dict) fatal("Cannot create dictionary.");
 
        struct rusage start, end;
        unsigned long long dt;
        char buf[100 + 1];
        struct myvalue value, *v;
-       int i, max = 10000000, max2;
+       int i, max = 100000, max2;
 
        // ------------------------------------------------------------------------
 
        getrusage(RUSAGE_SELF, &start);
-       dict->inserts = dict->deletes = dict->searches = 0ULL;
+       dict->stats->inserts = dict->stats->deletes = dict->stats->searches = 0ULL;
        fprintf(stderr, "Inserting %d entries in the dictionary\n", max);
        for(i = 0; i < max; i++) {
                value.i = i;
@@ -45,12 +46,12 @@ int main(int argc, char **argv) {
        getrusage(RUSAGE_SELF, &end);
        dt = (end.ru_utime.tv_sec * 1000000ULL + end.ru_utime.tv_usec) - (start.ru_utime.tv_sec * 1000000ULL + start.ru_utime.tv_usec);
        fprintf(stderr, "Added %d entries in %llu nanoseconds: %llu inserts per second\n", max, dt, max * 1000000ULL / dt);
-       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->inserts, dict->deletes, dict->searches);
+       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->stats->inserts, dict->stats->deletes, dict->stats->searches);
 
        // ------------------------------------------------------------------------
 
        getrusage(RUSAGE_SELF, &start);
-       dict->inserts = dict->deletes = dict->searches = 0ULL;
+       dict->stats->inserts = dict->stats->deletes = dict->stats->searches = 0ULL;
        fprintf(stderr, "Retrieving %d entries from the dictionary\n", max);
        for(i = 0; i < max; i++) {
                value.i = i;
@@ -65,12 +66,12 @@ int main(int argc, char **argv) {
        getrusage(RUSAGE_SELF, &end);
        dt = (end.ru_utime.tv_sec * 1000000ULL + end.ru_utime.tv_usec) - (start.ru_utime.tv_sec * 1000000ULL + start.ru_utime.tv_usec);
        fprintf(stderr, "Read %d entries in %llu nanoseconds: %llu searches per second\n", max, dt, max * 1000000ULL / dt);
-       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->inserts, dict->deletes, dict->searches);
+       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->stats->inserts, dict->stats->deletes, dict->stats->searches);
 
        // ------------------------------------------------------------------------
 
        getrusage(RUSAGE_SELF, &start);
-       dict->inserts = dict->deletes = dict->searches = 0ULL;
+       dict->stats->inserts = dict->stats->deletes = dict->stats->searches = 0ULL;
        fprintf(stderr, "Resetting %d entries in the dictionary\n", max);
        for(i = 0; i < max; i++) {
                value.i = i;
@@ -80,13 +81,13 @@ int main(int argc, char **argv) {
        }
        getrusage(RUSAGE_SELF, &end);
        dt = (end.ru_utime.tv_sec * 1000000ULL + end.ru_utime.tv_usec) - (start.ru_utime.tv_sec * 1000000ULL + start.ru_utime.tv_usec);
-       fprintf(stderr, "Reset %d entries in %llu nanoseconds: %llu inserts per second\n", max, dt, max * 1000000ULL / dt);
-       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->inserts, dict->deletes, dict->searches);
+       fprintf(stderr, "Reset %d entries in %llu nanoseconds: %llu resets per second\n", max, dt, max * 1000000ULL / dt);
+       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->stats->inserts, dict->stats->deletes, dict->stats->searches);
 
        // ------------------------------------------------------------------------
 
        getrusage(RUSAGE_SELF, &start);
-       dict->inserts = dict->deletes = dict->searches = 0ULL;
+       dict->stats->inserts = dict->stats->deletes = dict->stats->searches = 0ULL;
        fprintf(stderr, "Searching  %d non-existing entries in the dictionary\n", max);
        max2 = max * 2;
        for(i = max; i < max2; i++) {
@@ -99,13 +100,13 @@ int main(int argc, char **argv) {
        }
        getrusage(RUSAGE_SELF, &end);
        dt = (end.ru_utime.tv_sec * 1000000ULL + end.ru_utime.tv_usec) - (start.ru_utime.tv_sec * 1000000ULL + start.ru_utime.tv_usec);
-       fprintf(stderr, "Searched %d non-existing entries in %llu nanoseconds: %llu searches per second\n", max, dt, max * 1000000ULL / dt);
-       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->inserts, dict->deletes, dict->searches);
+       fprintf(stderr, "Searched %d non-existing entries in %llu nanoseconds: %llu not found searches per second\n", max, dt, max * 1000000ULL / dt);
+       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->stats->inserts, dict->stats->deletes, dict->stats->searches);
 
        // ------------------------------------------------------------------------
 
        getrusage(RUSAGE_SELF, &start);
-       dict->inserts = dict->deletes = dict->searches = 0ULL;
+       dict->stats->inserts = dict->stats->deletes = dict->stats->searches = 0ULL;
        fprintf(stderr, "Deleting %d entries from the dictionary\n", max);
        for(i = 0; i < max; i++) {
                value.i = i;
@@ -116,12 +117,12 @@ int main(int argc, char **argv) {
        getrusage(RUSAGE_SELF, &end);
        dt = (end.ru_utime.tv_sec * 1000000ULL + end.ru_utime.tv_usec) - (start.ru_utime.tv_sec * 1000000ULL + start.ru_utime.tv_usec);
        fprintf(stderr, "Deleted %d entries in %llu nanoseconds: %llu deletes per second\n", max, dt, max * 1000000ULL / dt);
-       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->inserts, dict->deletes, dict->searches);
+       fprintf(stderr, " > Dictionary: %llu inserts, %llu deletes, %llu searches\n\n", dict->stats->inserts, dict->stats->deletes, dict->stats->searches);
 
        // ------------------------------------------------------------------------
 
        getrusage(RUSAGE_SELF, &start);
-       dict->inserts = dict->deletes = dict->searches = 0ULL;
+       dict->stats->inserts = dict->stats->deletes = dict->stats->searches = 0ULL;
        fprintf(stderr, "Destroying dictionary\n");
        dictionary_destroy(dict);
        getrusage(RUSAGE_SELF, &end);
index d3576412b5dc1264a1068db2eeb1c1adca7a0542..3b9e8a90be5ab855e2b0f5a3927d01d2278aa944 100644 (file)
 
 #include "dictionary.h"
 
+// ----------------------------------------------------------------------------
+// dictionary statistics
+
+static inline void NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(DICTIONARY *dict) {
+       if(likely(dict->stats))
+               dict->stats->inserts++;
+}
+static inline void NETDATA_DICTIONARY_STATS_DELETES_PLUS1(DICTIONARY *dict) {
+       if(likely(dict->stats))
+               dict->stats->deletes++;
+}
+static inline void NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(DICTIONARY *dict) {
+       if(likely(dict->stats))
+               dict->stats->searches++;
+}
+static inline void NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(DICTIONARY *dict) {
+       if(likely(dict->stats))
+               dict->stats->entries++;
+}
+static inline void NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(DICTIONARY *dict) {
+       if(likely(dict->stats))
+               dict->stats->entries--;
+}
+
+
 // ----------------------------------------------------------------------------
 // dictionary locks
 
 static inline void dictionary_read_lock(DICTIONARY *dict) {
-       if(likely(!(dict->flags & DICTIONARY_FLAG_SINGLE_THREADED))) {
+       if(likely(dict->rwlock)) {
                // debug(D_DICTIONARY, "Dictionary READ lock");
-               pthread_rwlock_rdlock(&dict->rwlock);
+               pthread_rwlock_rdlock(dict->rwlock);
        }
 }
 
 static inline void dictionary_write_lock(DICTIONARY *dict) {
-       if(likely(!(dict->flags & DICTIONARY_FLAG_SINGLE_THREADED))) {
+       if(likely(dict->rwlock)) {
                // debug(D_DICTIONARY, "Dictionary WRITE lock");
-               pthread_rwlock_wrlock(&dict->rwlock);
+               pthread_rwlock_wrlock(dict->rwlock);
        }
 }
 
 static inline void dictionary_unlock(DICTIONARY *dict) {
-       if(likely(!(dict->flags & DICTIONARY_FLAG_SINGLE_THREADED))) {
+       if(likely(dict->rwlock)) {
                // debug(D_DICTIONARY, "Dictionary UNLOCK lock");
-               pthread_rwlock_unlock(&dict->rwlock);
+               pthread_rwlock_unlock(dict->rwlock);
        }
 }
 
@@ -123,9 +148,18 @@ DICTIONARY *dictionary_create(uint32_t flags) {
        DICTIONARY *dict = calloc(1, sizeof(DICTIONARY));
        if(unlikely(!dict)) fatal("Cannot allocate DICTIONARY");
 
-       avl_init(&dict->values_index, name_value_compare);
-       pthread_rwlock_init(&dict->rwlock, NULL);
+       if(flags & DICTIONARY_FLAG_WITH_STATISTICS) {
+               dict->stats = calloc(1, sizeof(struct dictionary_stats));
+               if(!dict->stats) fatal("Cannot allocate statistics for DICTIONARY");
+       }
+
+       if(!(flags & DICTIONARY_FLAG_SINGLE_THREADED)) {
+               dict->rwlock = calloc(1, sizeof(pthread_rwlock_t));
+               if(!dict->rwlock) fatal("Cannot allocate pthread_rwlock_t for DICTIONARY");
+               pthread_rwlock_init(dict->rwlock, NULL);
+       }
 
+       avl_init(&dict->values_index, name_value_compare);
        dict->flags = flags;
 
        return dict;
@@ -141,6 +175,12 @@ void dictionary_destroy(DICTIONARY *dict) {
 
        dictionary_unlock(dict);
 
+       if(dict->stats)
+               free(dict->stats);
+
+       if(dict->rwlock)
+               free(dict->rwlock);
+
        free(dict);
 }
 
index fe44d8146093f3c3e2fe0dc472b04880b14bbce1..c32d8bd92d82514ca6694e88ebaf0f6e5c3d8147 100644 (file)
@@ -6,6 +6,13 @@
 #ifndef NETDATA_DICTIONARY_H
 #define NETDATA_DICTIONARY_H 1
 
+struct dictionary_stats {
+       unsigned long long inserts;
+       unsigned long long deletes;
+       unsigned long long searches;
+       unsigned long long entries;
+};
+
 typedef struct name_value {
        avl avl;                                // the index - this has to be first!
 
@@ -21,34 +28,15 @@ typedef struct dictionary {
 
        uint8_t flags;
 
-#ifdef NETDATA_DICTIONARY_WITH_STATISTICS
-       unsigned long long inserts;
-       unsigned long long deletes;
-       unsigned long long searches;
-       unsigned long long entries;
-#endif /* NETDATA_DICTIONARY_WITH_STATISTICS */
-
-       pthread_rwlock_t rwlock;
+       struct dictionary_stats *stats;
+       pthread_rwlock_t *rwlock;
 } DICTIONARY;
 
-#ifdef NETDATA_DICTIONARY_WITH_STATISTICS
-#define NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict) (dict)->inserts++
-#define NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict) (dict)->deletes++
-#define NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict) (dict)->searches++
-#define NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict) (dict)->entries++
-#define NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict) (dict)->entries--
-#else /* NETDATA_DICTIONARY_WITH_STATISTICS */
-#define NETDATA_DICTIONARY_STATS_INSERTS_PLUS1(dict)
-#define NETDATA_DICTIONARY_STATS_DELETES_PLUS1(dict)
-#define NETDATA_DICTIONARY_STATS_SEARCHES_PLUS1(dict)
-#define NETDATA_DICTIONARY_STATS_ENTRIES_PLUS1(dict)
-#define NETDATA_DICTIONARY_STATS_ENTRIES_MINUS1(dict)
-#endif /* NETDATA_DICTIONARY_WITH_STATISTICS */
-
 #define DICTIONARY_FLAG_DEFAULT                                        0x00000000
 #define DICTIONARY_FLAG_SINGLE_THREADED                        0x00000001
 #define DICTIONARY_FLAG_VALUE_LINK_DONT_CLONE  0x00000002
 #define DICTIONARY_FLAG_NAME_LINK_DONT_CLONE   0x00000004
+#define DICTIONARY_FLAG_WITH_STATISTICS                        0x00000008
 
 extern DICTIONARY *dictionary_create(uint32_t flags);
 extern void dictionary_destroy(DICTIONARY *dict);