@cryptotaxi247 / netdata-1 / commits / 90b99fcf0

allow memory mode ram to use KSM; fixes #2284

Costa Tsaousis (ktsaou) committed Jun 7, 2017 at 01:55 UTC 90b99fcf0f40eee4dd9ded629a453eb242e46fd2
4 files changed +117 -85
src/common.c
+98 -78
@@ -943,105 +943,125 @@ inline char *trim_all(char *buffer) {
943 return buffer;
944 }
945
946 -void *mymmap(const char *filename, size_t size, int flags, int ksm) {
947 -#ifndef MADV_MERGEABLE
948 - (void)ksm;
949 -#endif
950 - static int log_madvise_1 = 1;
951 -#ifdef MADV_MERGEABLE
952 - static int log_madvise_2 = 1, log_madvise_3 = 1;
953 -#endif
954 - void *mem = NULL;
955 -
956 - errno = 0;
946 +static int memory_file_open(const char *filename, size_t size) {
947 int fd = open(filename, O_RDWR | O_CREAT | O_NOATIME, 0664);
948 if (fd != -1) {
949 if (lseek(fd, size, SEEK_SET) == (off_t) size) {
950 if (write(fd, "", 1) == 1) {
951 if (ftruncate(fd, size))
952 error("Cannot truncate file '%s' to size %zu. Will use the larger file.", filename, size);
953 + }
954 + else error("Cannot write to file '%s' at position %zu.", filename, size);
955 + }
956 + else error("Cannot seek file '%s' to size %zu.", filename, size);
957 + }
958 + else error("Cannot create/open file '%s'.", filename);
959
964 -#ifdef MADV_MERGEABLE
965 - if (flags & MAP_SHARED || !enable_ksm || !ksm) {
966 -#endif
967 - mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
968 - if (mem == MAP_FAILED) {
969 - error("Cannot allocate SHARED memory for file '%s'.", filename);
970 - mem = NULL;
971 - }
972 - else {
960 + return fd;
961 +}
962 +
963 +// mmap_shared is used for memory mode = map
964 +static void *memory_file_mmap(const char *filename, size_t size, int flags) {
965 + static int log_madvise = 1;
966 +
967 + int fd = -1;
968 + if(filename) {
969 + fd = memory_file_open(filename, size);
970 + if(fd == -1) return MAP_FAILED;
971 + }
972 +
973 + void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
974 + if (mem != MAP_FAILED) {
975 #ifdef NETDATA_LOG_ALLOCATIONS
974 - mmap_accounting(size);
976 + mmap_accounting(size);
977 #endif
976 - int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
977 - if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
978 -
979 - if (madvise(mem, size, advise) != 0 && log_madvise_1) {
980 - error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
981 - log_madvise_1--;
982 - }
983 - }
978 + int advise = MADV_SEQUENTIAL | MADV_DONTFORK;
979 + if (flags & MAP_SHARED) advise |= MADV_WILLNEED;
980 +
981 + if (madvise(mem, size, advise) != 0 && log_madvise) {
982 + error("Cannot advise the kernel about shared memory usage.");
983 + log_madvise--;
984 + }
985 + }
986 +
987 + if(fd != -1)
988 + close(fd);
989 +
990 + return mem;
991 +}
992 +
993 #ifdef MADV_MERGEABLE
985 - }
986 - else {
987 -/*
988 - // test - load the file into memory
989 - mem = calloc(1, size);
990 - if(mem) {
991 - if(lseek(fd, 0, SEEK_SET) == 0) {
992 - if(read(fd, mem, size) != (ssize_t)size)
993 - error("Cannot read from file '%s'", filename);
994 - }
995 - else
996 - error("Cannot seek to beginning of file '%s'.", filename);
997 - }
998 -*/
999 - mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
1000 - if (mem == MAP_FAILED) {
1001 - error("Cannot allocate PRIVATE ANONYMOUS memory for KSM for file '%s'.", filename);
1002 - mem = NULL;
1003 - }
1004 - else {
994 +static void *memory_file_mmap_ksm(const char *filename, size_t size, int flags) {
995 + static int log_madvise_2 = 1, log_madvise_3 = 1;
996 +
997 + int fd = -1;
998 + if(filename) {
999 + fd = memory_file_open(filename, size);
1000 + if(fd == -1) return MAP_FAILED;
1001 + }
1002 +
1003 + void *mem = mmap(NULL, size, PROT_READ | PROT_WRITE, flags | MAP_ANONYMOUS, -1, 0);
1004 + if (mem != MAP_FAILED) {
1005 #ifdef NETDATA_LOG_ALLOCATIONS
1006 - mmap_accounting(size);
1007 -#endif
1008 - if (lseek(fd, 0, SEEK_SET) == 0) {
1009 - if (read(fd, mem, size) != (ssize_t) size)
1010 - error("Cannot read from file '%s'", filename);
1011 - } else
1012 - error("Cannot seek to beginning of file '%s'.", filename);
1013 -
1014 - // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
1015 - if (madvise(mem, size, MADV_SEQUENTIAL | MADV_DONTFORK) != 0 && log_madvise_2) {
1016 - error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.",
1017 - filename);
1018 - log_madvise_2--;
1019 - }
1020 -
1021 - if (madvise(mem, size, MADV_MERGEABLE) != 0 && log_madvise_3) {
1022 - error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.",
1023 - filename);
1024 - log_madvise_3--;
1025 - }
1026 - }
1027 - }
1006 + mmap_accounting(size);
1007 #endif
1008 + if(fd != -1) {
1009 + if (lseek(fd, 0, SEEK_SET) == 0) {
1010 + if (read(fd, mem, size) != (ssize_t) size)
1011 + error("Cannot read from file '%s'", filename);
1012 + }
1013 + else error("Cannot seek to beginning of file '%s'.", filename);
1014 +
1015 + // don't use MADV_SEQUENTIAL|MADV_DONTFORK, they disable MADV_MERGEABLE
1016 + if (madvise(mem, size, MADV_SEQUENTIAL | MADV_DONTFORK) != 0 && log_madvise_2) {
1017 + error("Cannot advise the kernel about the memory usage (MADV_SEQUENTIAL|MADV_DONTFORK) of file '%s'.", filename);
1018 + log_madvise_2--;
1019 + }
1020 +
1021 + if (madvise(mem, size, MADV_MERGEABLE) != 0 && log_madvise_3) {
1022 + error("Cannot advise the kernel about the memory usage (MADV_MERGEABLE) of file '%s'.", filename);
1023 + log_madvise_3--;
1024 }
1030 - else
1031 - error("Cannot write to file '%s' at position %zu.", filename, size);
1025 }
1033 - else
1034 - error("Cannot seek file '%s' to size %zu.", filename, size);
1026 + }
1027
1028 + if(fd != -1)
1029 close(fd);
1037 - }
1030 +
1031 + return mem;
1032 +}
1033 +#else
1034 +static void *memory_file_mmap_ksm(const char *filename, size_t size, int flags) {
1035 +
1036 + if(filename)
1037 + return memory_file_mmap(filename, size, flags);
1038 +
1039 + // when KSM is not available and no filename is given (memory mode = ram),
1040 + // we just report failure
1041 + return MAP_FAILED;
1042 +}
1043 +#endif
1044 +
1045 +void *mymmap(const char *filename, size_t size, int flags, int ksm) {
1046 + void *mem = NULL;
1047 +
1048 + if (filename && (flags & MAP_SHARED || !enable_ksm || !ksm))
1049 + // memory mode = map | save
1050 + // when KSM is not enabled
1051 + // MAP_SHARED is used for memory mode = map (no KSM possible)
1052 + mem = memory_file_mmap(filename, size, flags);
1053 +
1054 else
1039 - error("Cannot create/open file '%s'.", filename);
1055 + // memory mode = save | ram
1056 + // when KSM is enabled
1057 + // for memory mode = ram, the filename is NULL
1058 + mem = memory_file_mmap_ksm(filename, size, flags);
1059
1060 + if(mem == MAP_FAILED) return NULL;
1061 return mem;
1062 }
1063
1044 -int savememory(const char *filename, void *mem, size_t size) {
1064 +int memory_file_save(const char *filename, void *mem, size_t size) {
1065 char tmpfilename[FILENAME_MAX + 1];
1066
1067 snprintfz(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long) getpid());
src/common.h
+1 -1
@@ -271,7 +271,7 @@ extern void freez(void *ptr);
271 extern void json_escape_string(char *dst, const char *src, size_t size);
272
273 extern void *mymmap(const char *filename, size_t size, int flags, int ksm);
274 -extern int savememory(const char *filename, void *mem, size_t size);
274 +extern int memory_file_save(const char *filename, void *mem, size_t size);
275
276 extern int fd_is_valid(int fd);
277
src/rrddim.c
+8 -2
@@ -71,8 +71,14 @@ RRDDIM *rrddim_add_custom(RRDSET *st, const char *id, const char *name, collecte
71 rrdset_strncpyz_name(filename, id, FILENAME_MAX);
72 snprintfz(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
73
74 - if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP) {
75 - rd = (RRDDIM *)mymmap(fullfilename, size, ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 1);
74 + if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP || memory_mode == RRD_MEMORY_MODE_RAM) {
75 + rd = (RRDDIM *)mymmap(
76 + (memory_mode == RRD_MEMORY_MODE_RAM)?NULL:fullfilename
77 + , size
78 + , ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE)
79 + , 1
80 + );
81 +
82 if(likely(rd)) {
83 // we have a file mapped for rd
84
src/rrdset.c
+10 -4
@@ -294,14 +294,14 @@ void rrdset_save(RRDSET *st) {
294
295 if(st->rrd_memory_mode == RRD_MEMORY_MODE_SAVE) {
296 debug(D_RRD_STATS, "Saving stats '%s' to '%s'.", st->name, st->cache_filename);
297 - savememory(st->cache_filename, st, st->memsize);
297 + memory_file_save(st->cache_filename, st, st->memsize);
298 }
299
300 RRDDIM *rd;
301 rrddim_foreach_read(rd, st) {
302 if(likely(rd->rrd_memory_mode == RRD_MEMORY_MODE_SAVE)) {
303 debug(D_RRD_STATS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_filename);
304 - savememory(rd->cache_filename, rd, rd->memsize);
304 + memory_file_save(rd->cache_filename, rd, rd->memsize);
305 }
306 }
307 }
@@ -421,8 +421,14 @@ RRDSET *rrdset_create_custom(
421 debug(D_RRD_CALLS, "Creating RRD_STATS for '%s.%s'.", type, id);
422
423 snprintfz(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
424 - if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP) {
425 - st = (RRDSET *) mymmap(fullfilename, size, ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE), 0);
424 + if(memory_mode == RRD_MEMORY_MODE_SAVE || memory_mode == RRD_MEMORY_MODE_MAP || memory_mode == RRD_MEMORY_MODE_RAM) {
425 + st = (RRDSET *) mymmap(
426 + (memory_mode == RRD_MEMORY_MODE_RAM)?NULL:fullfilename
427 + , size
428 + , ((memory_mode == RRD_MEMORY_MODE_MAP) ? MAP_SHARED : MAP_PRIVATE)
429 + , 0
430 + );
431 +
432 if(st) {
433 memset(&st->avl, 0, sizeof(avl));
434 memset(&st->avlname, 0, sizeof(avl));