Skip to content

Commit

Permalink
[PATCH] Basic KSM Support
Browse files Browse the repository at this point in the history
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
  • Loading branch information
showp1984 authored and greg-pe committed Feb 10, 2012
1 parent 3dd2ecf commit 0a1dfa0
Showing 1 changed file with 60 additions and 0 deletions.
60 changes: 60 additions & 0 deletions vm/native/dalvik_system_Zygote.cpp
Expand Up @@ -23,6 +23,8 @@
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <stdio.h>
#include <grp.h>
#include <errno.h>
#include <paths.h>
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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 */
}
Expand Down

0 comments on commit 0a1dfa0

Please sign in to comment.