From 0a1dfa0dfa6065c0b7eca520750e5bbb6102d1ca Mon Sep 17 00:00:00 2001 From: showp1984 Date: Wed, 25 Jan 2012 02:56:34 -0800 Subject: [PATCH] [PATCH] Basic KSM Support Be sure to add '#define MADV_MERGEABLE 12' to bionic/libc/include/sys/mman.h so we can have a central place for this parse the process memory map and inform madvise common HEAP/Stack regions on fork from zygote These then can be used by the kernel KSM module to re-join (copy on write) pages between the various dalvik processes. As is on a fully loaded system you can expect ~12MB to be indicated to be scanned by KSM.. of this 10-15% will be saved; as such a recommend a very slow scan until as any logic to stop scanning while sleeping will require another process and remove all memory savings provided by this logic. To activate on a KSM kernel (2min for full scan of ~16m and 1%CPU): echo 4000 > /sys/kernel/mm/ksm/sleep_millisecs echo 128 > /sys/kernel/mm/ksm/pages_to_scan echo 1 > /sys/kernel/mm/ksm/run Newer kernels only require the last line. In future additional memory regions and kernel logic may improve this. Change-Id: I271cbee74a1f02a89c34c6ee9006a4ea81360154 --- vm/native/dalvik_system_Zygote.cpp | 60 ++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/vm/native/dalvik_system_Zygote.cpp b/vm/native/dalvik_system_Zygote.cpp index 31fecfd2d..0de013141 100644 --- a/vm/native/dalvik_system_Zygote.cpp +++ b/vm/native/dalvik_system_Zygote.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -355,6 +357,63 @@ static int setCapabilities(int64_t permitted, int64_t effective) return 0; } +/* + * Basic KSM Support + */ +#ifndef MADV_MERGEABLE +#define MADV_MERGEABLE 12 +#endif + +static inline void pushAnonymousPagesToKSM(void) +{ + FILE *fp; + char section[100]; + char perms[5]; + unsigned long start, end, misc; + int ch, offset; + + fp = fopen("/proc/self/maps","r"); + + if (fp != NULL) { + while (fscanf(fp, "%lx-%lx %4s %lx %lx:%lx %ld", + &start, &end, perms, &misc, &misc, &misc, &misc) == 7) + { + /* Read the sections name striping any preceeding spaces + and truncating to 100char (99 + \0)*/ + section[0] = 0; + offset = 0; + while(1) + { + ch = fgetc(fp); + if (ch == '\n' || ch == EOF) { + break; + } + if ((offset == 0) && (ch == ' ')) { + continue; + } + if ((offset + 1) < 100) { + section[offset]=ch; + section[offset+1]=0; + offset++; + } + } + /* now decide if we want to scan the section or not: + for now we scan Anonymous (sections with no file name) stack and + heap sections*/ + if (( section[0] == 0) || + (strcmp(section,"[stack]") == 0) || + (strcmp(section,"[heap]") == 0)) + { + /* The section matches pass it into madvise */ + madvise((void*) start, (size_t) end-start, MADV_MERGEABLE); + } + if (ch == EOF) { + break; + } + } + fclose(fp); + } +} /* * Utility routine to fork zygote and specialize the child process. */ @@ -468,6 +527,7 @@ static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer) LOGE("error in post-zygote initialization"); dvmAbort(); } + pushAnonymousPagesToKSM(); } else if (pid > 0) { /* the parent process */ }