Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4755b72e authored by San Mehat's avatar San Mehat Committed by Greg Kroah-Hartman
Browse files

staging: android: lowmemkiller: Substantially reduce overhead during reclaim



This patch optimizes lowmemkiller to not do any work when it has an outstanding
kill-request. This greatly reduces the pressure on the task_list lock
(improving interactivity), as well as improving the vmscan performance
when under heavy memory pressure (by up to 20x in tests).

Note: For this enhancement to work, you need CONFIG_PROFILING

Signed-off-by: default avatarSan Mehat <san@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 4964cd41
Loading
Loading
Loading
Loading
+43 −0
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
#include <linux/mm.h>
#include <linux/oom.h>
#include <linux/sched.h>
#include <linux/profile.h>
#include <linux/notifier.h>

static uint32_t lowmem_debug_level = 2;
static int lowmem_adj[6] = {
@@ -51,12 +53,32 @@ static size_t lowmem_minfree[6] = {
};
static int lowmem_minfree_size = 4;

static struct task_struct *lowmem_deathpending;

#define lowmem_print(level, x...)			\
	do {						\
		if (lowmem_debug_level >= (level))	\
			printk(x);			\
	} while (0)

static int
task_notify_func(struct notifier_block *self, unsigned long val, void *data);

static struct notifier_block task_nb = {
	.notifier_call	= task_notify_func,
};

static int
task_notify_func(struct notifier_block *self, unsigned long val, void *data)
{
	struct task_struct *task = data;
	if (task == lowmem_deathpending) {
		lowmem_deathpending = NULL;
		task_handoff_unregister(&task_nb);
	}
	return NOTIFY_OK;
}

static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
{
	struct task_struct *p;
@@ -71,6 +93,18 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
	int other_free = global_page_state(NR_FREE_PAGES);
	int other_file = global_page_state(NR_FILE_PAGES);

	/*
	 * If we already have a death outstanding, then
	 * bail out right away; indicating to vmscan
	 * that we have nothing further to offer on
	 * this pass.
	 *
	 * Note: Currently you need CONFIG_PROFILING
	 * for this to work correctly.
	 */
	if (lowmem_deathpending)
		return 0;

	if (lowmem_adj_size < array_size)
		array_size = lowmem_adj_size;
	if (lowmem_minfree_size < array_size)
@@ -142,6 +176,15 @@ static int lowmem_shrink(int nr_to_scan, gfp_t gfp_mask)
		lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",
			     selected->pid, selected->comm,
			     selected_oom_adj, selected_tasksize);
		/*
		 * If CONFIG_PROFILING is off, then task_handoff_register()
		 * is a nop. In that case we don't want to stall the killer
		 * by setting lowmem_deathpending.
		 */
#ifdef CONFIG_PROFILING
		lowmem_deathpending = selected;
		task_handoff_register(&task_nb);
#endif
		force_sig(SIGKILL, selected);
		rem -= selected_tasksize;
	}