#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
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;
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);
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
// --------------------------------------------------------------------
+ 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);
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;
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);