diff options
author | Sherry Yang <sherryy@android.com> | 2017-08-25 19:05:50 -0700 |
---|---|---|
committer | Sherry Yang <sherryy@android.com> | 2017-08-25 20:11:03 -0700 |
commit | 7277af87cc2a36661222c20ab7173c7933cd1a34 (patch) | |
tree | 81628518da27efcd0c91ca511a4d18e7ee247d9a /alloc-stress | |
parent | 14f2ee3581b867e70567693b4f3520a80ad2d9a3 (diff) | |
download | extras-7277af87cc2a36661222c20ab7173c7933cd1a34.tar.gz |
Memory pressure
Create continuous memory pressure by adjusting
a child process's oom score and allocate in
the child. When a child is killed by
the low-memory-killer, fork another process and
continues until the program is killed or certain
number of iterations has reached.
Bug: 63926541
Test: run mem-pressure on target
Change-Id: Ic8ee60da7519c750de4bd690f26e31fa80c5cd49
Diffstat (limited to 'alloc-stress')
-rw-r--r-- | alloc-stress/Android.mk | 10 | ||||
-rw-r--r-- | alloc-stress/mem-pressure.cpp | 107 |
2 files changed, 117 insertions, 0 deletions
diff --git a/alloc-stress/Android.mk b/alloc-stress/Android.mk index ec19d798..ad46f262 100644 --- a/alloc-stress/Android.mk +++ b/alloc-stress/Android.mk @@ -12,3 +12,13 @@ LOCAL_SHARED_LIBRARIES := libhardware libcutils LOCAL_SRC_FILES := \ alloc-stress.cpp include $(BUILD_EXECUTABLE) + +include $(CLEAR_VARS) +LOCAL_MODULE := mem-pressure +LOCAL_CFLAGS += -g -Wall -Werror -Wno-missing-field-initializers -Wno-sign-compare +ifneq ($(ENABLE_MEM_CGROUPS),) + LOCAL_CFLAGS += -DENABLE_MEM_CGROUPS +endif +LOCAL_SRC_FILES := \ + mem-pressure.cpp +include $(BUILD_EXECUTABLE) diff --git a/alloc-stress/mem-pressure.cpp b/alloc-stress/mem-pressure.cpp new file mode 100644 index 00000000..777015d3 --- /dev/null +++ b/alloc-stress/mem-pressure.cpp @@ -0,0 +1,107 @@ +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/wait.h> +#include <getopt.h> + +void *alloc_set(size_t size) { + void *addr = NULL; + + addr = malloc(size); + if (!addr) { + printf("Allocating %zd MB failed\n", size / 1024 / 1024); + } else { + memset(addr, 0, size); + } + return addr; +} + +void add_pressure(size_t *shared, size_t size, size_t step_size, + size_t duration, const char *oom_score) { + int fd, ret; + + fd = open("/proc/self/oom_score_adj", O_WRONLY); + ret = write(fd, oom_score, strlen(oom_score)); + if (ret < 0) { + printf("Writing oom_score_adj failed with err %s\n", + strerror(errno)); + } + close(fd); + + if (alloc_set(size)) { + *shared = size; + } + + while (alloc_set(step_size)) { + size += step_size; + *shared = size; + usleep(duration); + } +} + +void usage() +{ + printf("Usage: [OPTIONS]\n\n" + " -d N: Duration in microsecond to sleep between each allocation.\n" + " -i N: Number of iterations to run the alloc process.\n" + " -o N: The oom_score to set the child process to before alloc.\n" + " -s N: Number of bytes to allocate in an alloc process loop.\n" + ); +} + +int main(int argc, char *argv[]) +{ + pid_t pid; + size_t *shared; + int c, i = 0; + + size_t duration = 1000; + int iterations = 0; + const char *oom_score = "899"; + size_t step_size = 2 * 1024 * 1024; // 2 MB + size_t size = step_size; + + while ((c = getopt(argc, argv, "hi:d:o:s:")) != -1) { + switch (c) + { + case 'i': + iterations = atoi(optarg); + break; + case 'd': + duration = atoi(optarg); + break; + case 'o': + oom_score = optarg; + break; + case 's': + step_size = atoi(optarg); + break; + case 'h': + usage(); + abort(); + default: + abort(); + } + } + + shared = (size_t *)mmap(NULL, sizeof(size_t), PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_SHARED, 0, 0); + + while (iterations == 0 || i < iterations) { + *shared = 0; + pid = fork(); + if (!pid) { + /* Child */ + add_pressure(shared, size, step_size, duration, oom_score); + /* Shoud not get here */ + exit(0); + } else { + wait(NULL); + printf("Child %d allocated %zd MB\n", i, + *shared / 1024 / 1024); + size = *shared / 2; + } + i++; + } +} |