Commit 6f04f48d authored by Suleiman Souhlal's avatar Suleiman Souhlal Committed by Linus Torvalds

mm: only force scan in reclaim when none of the LRUs are big enough.

Prior to this change, we would decide whether to force scan a LRU during
reclaim if that LRU itself was too small for the current priority.
However, this can lead to the file LRU getting force scanned even if
there are a lot of anonymous pages we can reclaim, leading to hot file
pages getting needlessly reclaimed.

To address this, we instead only force scan when none of the reclaimable
LRUs are big enough.

Gives huge improvements with zswap.  For example, when doing -j20 kernel
build in a 500MB container with zswap enabled, runtime (in seconds) is
greatly reduced:

x without this change
+ with this change
    N           Min           Max        Median           Avg        Stddev
x   5       700.997       790.076       763.928        754.05      39.59493
+   5       141.634       197.899       155.706         161.9     21.270224
Difference at 95.0% confidence
        -592.15 +/- 46.3521
        -78.5293% +/- 6.14709%
        (Student's t, pooled s = 31.7819)

Should also give some improvements in regular (non-zswap) swap cases.

Yes, hughd found significant speedup using regular swap, with several
memcgs under pressure; and it should also be effective in the non-memcg
case, whenever one or another zone LRU is forced too small.
Signed-off-by: default avatarSuleiman Souhlal <suleiman@google.com>
Signed-off-by: default avatarHugh Dickins <hughd@google.com>
Cc: Suleiman Souhlal <suleiman@google.com>
Cc: Mel Gorman <mgorman@suse.de>
Acked-by: default avatarRik van Riel <riel@redhat.com>
Acked-by: default avatarRafael Aquini <aquini@redhat.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Yuanhan Liu <yuanhan.liu@linux.intel.com>
Cc: Seth Jennings <sjennings@variantweb.net>
Cc: Bob Liu <bob.liu@oracle.com>
Cc: Minchan Kim <minchan@kernel.org>
Cc: Luigi Semenzato <semenzato@google.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent c86c97ff
...@@ -1866,6 +1866,8 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, ...@@ -1866,6 +1866,8 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
bool force_scan = false; bool force_scan = false;
unsigned long ap, fp; unsigned long ap, fp;
enum lru_list lru; enum lru_list lru;
bool some_scanned;
int pass;
/* /*
* If the zone or memcg is small, nr[l] can be 0. This * If the zone or memcg is small, nr[l] can be 0. This
...@@ -1989,39 +1991,49 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc, ...@@ -1989,39 +1991,49 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
fraction[1] = fp; fraction[1] = fp;
denominator = ap + fp + 1; denominator = ap + fp + 1;
out: out:
for_each_evictable_lru(lru) { some_scanned = false;
int file = is_file_lru(lru); /* Only use force_scan on second pass. */
unsigned long size; for (pass = 0; !some_scanned && pass < 2; pass++) {
unsigned long scan; for_each_evictable_lru(lru) {
int file = is_file_lru(lru);
unsigned long size;
unsigned long scan;
size = get_lru_size(lruvec, lru); size = get_lru_size(lruvec, lru);
scan = size >> sc->priority; scan = size >> sc->priority;
if (!scan && force_scan) if (!scan && pass && force_scan)
scan = min(size, SWAP_CLUSTER_MAX); scan = min(size, SWAP_CLUSTER_MAX);
switch (scan_balance) { switch (scan_balance) {
case SCAN_EQUAL: case SCAN_EQUAL:
/* Scan lists relative to size */ /* Scan lists relative to size */
break; break;
case SCAN_FRACT: case SCAN_FRACT:
/*
* Scan types proportional to swappiness and
* their relative recent reclaim efficiency.
*/
scan = div64_u64(scan * fraction[file],
denominator);
break;
case SCAN_FILE:
case SCAN_ANON:
/* Scan one type exclusively */
if ((scan_balance == SCAN_FILE) != file)
scan = 0;
break;
default:
/* Look ma, no brain */
BUG();
}
nr[lru] = scan;
/* /*
* Scan types proportional to swappiness and * Skip the second pass and don't force_scan,
* their relative recent reclaim efficiency. * if we found something to scan.
*/ */
scan = div64_u64(scan * fraction[file], denominator); some_scanned |= !!scan;
break;
case SCAN_FILE:
case SCAN_ANON:
/* Scan one type exclusively */
if ((scan_balance == SCAN_FILE) != file)
scan = 0;
break;
default:
/* Look ma, no brain */
BUG();
} }
nr[lru] = scan;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment