mm: vmpressure: make vmpressure window variable

Right now the vmpressure window is of constant size 2MB, which
works well with the following exceptions.
1) False vmpressure triggers are seen when the RAM size is greater
than 3GB. This results in lowmemorykiller, which uses vmpressure
events, killing tasks unnecessarily.
2) Vmpressure events are received late under memory pressure. This
behaviour is seen prominently in <=2GB RAM targets. This results in
lowmemorykiller kicking in late to kill tasks resulting in avoidable
page cache reclaim.

The problem analysis shows that the issue is with the constant size
of the vmpressure window which does not adapt to the varying memory
conditions. This patch recalculates the vmpressure window size at
the end of each window. The chosen window size is proportional to
the total of free and cached memory at that point.

Change-Id: I7e9ef4ddd82e2c2dd04ce09ec8d58a8829cfb64d
Signed-off-by: Vinayak Menon <vinmenon@codeaurora.org>
fourteen
Vinayak Menon 8 years ago committed by Jenna
parent ab6833c737
commit d760fac84a
  1. 42
      mm/vmpressure.c

@ -27,6 +27,22 @@
#include <linux/module.h>
#include <linux/vmpressure.h>
/*
* The window size (vmpressure_win) is the number of scanned pages before
* we try to analyze scanned/reclaimed ratio. So the window is used as a
* rate-limit tunable for the "low" level notification, and also for
* averaging the ratio for medium/critical levels. Using small window
* sizes can cause lot of false positives, but too big window size will
* delay the notifications.
*
* As the vmscan reclaimer logic works with chunks which are multiple of
* SWAP_CLUSTER_MAX, it makes sense to use it for the window size as well.
*
* TODO: Make the window size depend on machine size, as we do for vmstat
* thresholds. Currently we set it to 512 pages (2MB for 4KB pages).
*/
static unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16;
/*
* These thresholds are used when we account memory pressure through
* scanned/reclaimed ratio. The current values were chosen empirically. In
@ -436,6 +452,29 @@ static void vmpressure_memcg(gfp_t gfp, struct mem_cgroup *memcg, bool tree,
}
#endif
static void calculate_vmpressure_win(void)
{
long x;
x = global_node_page_state(NR_FILE_PAGES) -
global_node_page_state(NR_SHMEM) -
total_swapcache_pages() +
global_zone_page_state(NR_FREE_PAGES);
if (x < 1)
x = 1;
/*
* For low (free + cached), vmpressure window should be
* small, and high for higher values of (free + cached).
* But it should not be linear as well. This ensures
* timely vmpressure notifications when system is under
* memory pressure, and optimal number of events when
* cached is high. The sqaure root function is empirically
* found to serve the purpose.
*/
x = int_sqrt(x);
vmpressure_win = x;
}
static void vmpressure_global(gfp_t gfp, unsigned long scanned,
unsigned long reclaimed)
{
@ -450,6 +489,9 @@ static void vmpressure_global(gfp_t gfp, unsigned long scanned,
return;
spin_lock(&vmpr->sr_lock);
if (!vmpr->scanned)
calculate_vmpressure_win();
vmpr->scanned += scanned;
vmpr->reclaimed += reclaimed;

Loading…
Cancel
Save