]> arthur.barton.de Git - netdata.git/commitdiff
added config option "memory deduplication (ksm) = yes/no" to control memory deduplica...
authorCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sun, 20 Dec 2015 02:32:16 +0000 (04:32 +0200)
committerCosta Tsaousis (ktsaou) <costa@tsaousis.gr>
Sun, 20 Dec 2015 02:32:16 +0000 (04:32 +0200)
src/common.c
src/common.h
src/main.c
src/rrd.c

index 2df676f90216253f4e7584e242ba697d6e354d1f..63fed585111b98e3a326cf417ccdf286aa473b73 100755 (executable)
 
 #include "log.h"
 #include "common.h"
+#include "appconfig.h"
 
 char *global_host_prefix = "";
+int enable_ksm = 1;
 
 /*
 // http://stackoverflow.com/questions/7666509/hash-function-for-string
@@ -107,7 +109,7 @@ char *trim(char *s)
        return s;
 }
 
-void *mymmap(const char *filename, unsigned long size, int flags)
+void *mymmap(const char *filename, unsigned long size, int flags, int ksm)
 {
        int fd;
        void *mem = NULL;
@@ -117,14 +119,35 @@ void *mymmap(const char *filename, unsigned long size, int flags)
        if(fd != -1) {
                if(lseek(fd, size, SEEK_SET) == (long)size) {
                        if(write(fd, "", 1) == 1) {
-
                                if(ftruncate(fd, size))
                                        error("Cannot truncate file '%s' to size %ld. Will use the larger file.", filename, size);
 
-                               mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, fd, 0);
-                               if(mem) {
-                                       if(madvise(mem, size, MADV_SEQUENTIAL|MADV_DONTFORK|MADV_WILLNEED) != 0)
-                                               error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
+                               if(flags & MAP_SHARED || !enable_ksm || !ksm) {
+                                       mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, fd, 0);
+                                       if(mem) {
+                                               int advise = MADV_SEQUENTIAL|MADV_DONTFORK;
+                                               if(flags & MAP_SHARED) advise |= MADV_WILLNEED;
+
+                                               if(madvise(mem, size, advise) != 0)
+                                                       error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
+                                       }
+                               }
+                               else {
+                                       mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags|MAP_ANONYMOUS, -1, 0);
+                                       if(mem) {
+                                               if(lseek(fd, 0, SEEK_SET) == 0) {
+                                                       if(read(fd, mem, size) != size)
+                                                               error("Cannot read from file '%s'", filename);
+                                               }
+                                               else
+                                                       error("Cannot seek to beginning of file '%s'.", filename);
+
+                                               // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
+                                               if(madvise(mem, size, MADV_MERGEABLE) != 0)
+                                                       error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
+                                       }
+                                       else
+                                               error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
                                }
                        }
                        else error("Cannot write to file '%s' at position %ld.", filename, size);
index 46af8bc867d163e135ff166a060bdc1f33af3833..ba00af74fda609fcda6efc9e944d4caae6d2bd56 100755 (executable)
@@ -17,12 +17,13 @@ extern void strreverse(char* begin, char* end);
 extern char *mystrsep(char **ptr, char *s);
 extern char *trim(char *s);
 
-extern void *mymmap(const char *filename, unsigned long size, int flags);
+extern void *mymmap(const char *filename, unsigned long size, int flags, int ksm);
 extern int savememory(const char *filename, void *mem, unsigned long size);
 
 extern int fd_is_valid(int fd);
 
 extern char *global_host_prefix;
+extern int enable_ksm;
 
 /* Number of ticks per second */
 #define HZ             hz
index 11d69cdb1591b3b3070f0ad7dc78ed354da48c5e..1126c4386650b71aef2b363f908dd96ca908c68d 100755 (executable)
@@ -289,6 +289,11 @@ int main(int argc, char **argv)
 
                // --------------------------------------------------------------------
 
+               enable_ksm = config_get_boolean("global", "memory deduplication (ksm)", enable_ksm);
+
+               // --------------------------------------------------------------------
+
+
                global_host_prefix = config_get("global", "host access prefix", "");
                setenv("NETDATA_HOST_PREFIX", global_host_prefix, 1);
 
index 3b35b4aade352d4c4f01e82eb3d55d466b8afc4d..9604337df33d06ccde7760bf656b08a694f29a30 100755 (executable)
--- a/src/rrd.c
+++ b/src/rrd.c
@@ -353,7 +353,7 @@ RRDSET *rrdset_create(const char *type, const char *id, const char *name, const
        debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);
 
        snprintf(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
-       if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE));
+       if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) st = (RRDSET *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 0);
        if(st) {
                if(strcmp(st->magic, RRDSET_MAGIC) != 0) {
                        errno = 0;
@@ -468,7 +468,7 @@ RRDDIM *rrddim_add(RRDSET *st, const char *id, const char *name, long multiplier
 
        rrdset_strncpy_name(filename, id, FILENAME_MAX);
        snprintf(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
-       if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE));
+       if(rrd_memory_mode != RRD_MEMORY_MODE_RAM) rd = (RRDDIM *)mymmap(fullfilename, size, ((rrd_memory_mode == RRD_MEMORY_MODE_MAP)?MAP_SHARED:MAP_PRIVATE), 1);
        if(rd) {
                struct timeval now;
                gettimeofday(&now, NULL);