OSDN Git Service

Memory pressure
authorSherry Yang <sherryy@android.com>
Sat, 26 Aug 2017 02:05:50 +0000 (19:05 -0700)
committerSherry Yang <sherryy@android.com>
Sat, 26 Aug 2017 03:11:03 +0000 (20:11 -0700)
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

alloc-stress/Android.mk
alloc-stress/mem-pressure.cpp [new file with mode: 0644]

index ec19d79..ad46f26 100644 (file)
@@ -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 (file)
index 0000000..777015d
--- /dev/null
@@ -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++;
+    }
+}