aboutsummaryrefslogtreecommitdiffstats
path: root/mm/vmscan.c
diff options
context:
space:
mode:
authorSuleiman Souhlal <suleiman@google.com>2014-06-04 19:06:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 19:53:56 -0400
commit6f04f48dc9c0433e2bb687f5f7f7af1aba97b04d (patch)
tree0f396e26a4804af13e9004956ec1c5b9ac18ce6e /mm/vmscan.c
parentc86c97ff42cd6c6d1bd29eca4dfabeaf2b7f1020 (diff)
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: Suleiman Souhlal <suleiman@google.com> Signed-off-by: Hugh Dickins <hughd@google.com> Cc: Suleiman Souhlal <suleiman@google.com> Cc: Mel Gorman <mgorman@suse.de> Acked-by: Rik van Riel <riel@redhat.com> Acked-by: Rafael 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: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmscan.c')
-rw-r--r--mm/vmscan.c66
1 files changed, 39 insertions, 27 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 32c661d66a45..7901cb749e17 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1866,6 +1866,8 @@ static void get_scan_count(struct lruvec *lruvec, struct scan_control *sc,
1866 bool force_scan = false; 1866 bool force_scan = false;
1867 unsigned long ap, fp; 1867 unsigned long ap, fp;
1868 enum lru_list lru; 1868 enum lru_list lru;
1869 bool some_scanned;
1870 int pass;
1869 1871
1870 /* 1872 /*
1871 * If the zone or memcg is small, nr[l] can be 0. This 1873 * 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 fraction[1] = fp; 1991 fraction[1] = fp;
1990 denominator = ap + fp + 1; 1992 denominator = ap + fp + 1;
1991out: 1993out:
1992 for_each_evictable_lru(lru) { 1994 some_scanned = false;
1993 int file = is_file_lru(lru); 1995 /* Only use force_scan on second pass. */
1994 unsigned long size; 1996 for (pass = 0; !some_scanned && pass < 2; pass++) {
1995 unsigned long scan; 1997 for_each_evictable_lru(lru) {
1998 int file = is_file_lru(lru);
1999 unsigned long size;
2000 unsigned long scan;
1996 2001
1997 size = get_lru_size(lruvec, lru); 2002 size = get_lru_size(lruvec, lru);
1998 scan = size >> sc->priority; 2003 scan = size >> sc->priority;
1999 2004
2000 if (!scan && force_scan) 2005 if (!scan && pass && force_scan)
2001 scan = min(size, SWAP_CLUSTER_MAX); 2006 scan = min(size, SWAP_CLUSTER_MAX);
2002 2007
2003 switch (scan_balance) { 2008 switch (scan_balance) {
2004 case SCAN_EQUAL: 2009 case SCAN_EQUAL:
2005 /* Scan lists relative to size */ 2010 /* Scan lists relative to size */
2006 break; 2011 break;
2007 case SCAN_FRACT: 2012 case SCAN_FRACT:
2013 /*
2014 * Scan types proportional to swappiness and
2015 * their relative recent reclaim efficiency.
2016 */
2017 scan = div64_u64(scan * fraction[file],
2018 denominator);
2019 break;
2020 case SCAN_FILE:
2021 case SCAN_ANON:
2022 /* Scan one type exclusively */
2023 if ((scan_balance == SCAN_FILE) != file)
2024 scan = 0;
2025 break;
2026 default:
2027 /* Look ma, no brain */
2028 BUG();
2029 }
2030 nr[lru] = scan;
2008 /* 2031 /*
2009 * Scan types proportional to swappiness and 2032 * Skip the second pass and don't force_scan,
2010 * their relative recent reclaim efficiency. 2033 * if we found something to scan.
2011 */ 2034 */
2012 scan = div64_u64(scan * fraction[file], denominator); 2035 some_scanned |= !!scan;
2013 break;
2014 case SCAN_FILE:
2015 case SCAN_ANON:
2016 /* Scan one type exclusively */
2017 if ((scan_balance == SCAN_FILE) != file)
2018 scan = 0;
2019 break;
2020 default:
2021 /* Look ma, no brain */
2022 BUG();
2023 } 2036 }
2024 nr[lru] = scan;
2025 } 2037 }
2026} 2038}
2027 2039