If most processes reside in memory cgroups protected with memory.low, there won't be a lot of pages in the root cgroup's lruvec so that the lru scanned/eligible ratio can get high even on the initial scan priority. In this case global slab caches will be evicted far too aggressively. Tcache/tswap are especially affected - if the node is undercommitted, they may occupy gigabytes of RAM which can be dropped in an instant even on very low memory pressure.
To fix this, we forge scanned/eligible ratio passed to slab shrinkers if the number of pages on the root lruvec is small. Signed-off-by: Vladimir Davydov <[email protected]> --- mm/vmscan.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/mm/vmscan.c b/mm/vmscan.c index 0406c11287f5..a7cc964f0835 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2388,10 +2388,29 @@ static void shrink_zone(struct zone *zone, struct scan_control *sc, * Shrink the slab caches in the same proportion that * the eligible LRU pages were scanned. */ - if (global_reclaim(sc) && is_classzone) + if (global_reclaim(sc) && is_classzone) { + unsigned long scanned, eligible; + + scanned = sc->nr_scanned - nr_scanned; + eligible = zone_lru_pages; + + /* + * If most processes reside in memory cgroups protected + * with memory.low there won't be a lot of user pages + * in the root lruvec so that the lru scanned/eligible + * ratio ratio can get high even on the default scan + * priority. In order not to subject memcg unaware slab + * caches to disproportionately high pressure, we forge + * the ratio in this case. + */ + if (eligible >> sc->priority == 0) { + scanned = 1000; + eligible = 1000 << sc->priority; + } + shrink_slab(slab_gfp, zone_to_nid(zone), NULL, - sc->nr_scanned - nr_scanned, - zone_lru_pages); + scanned, eligible); + } if (reclaim_state) { sc->nr_reclaimed += reclaim_state->reclaimed_slab; -- 2.1.4 _______________________________________________ Devel mailing list [email protected] https://lists.openvz.org/mailman/listinfo/devel
